mixed_table.go 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160
  1. package excel
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "eta_gn/eta_api/models/data_manage"
  6. "eta_gn/eta_api/models/data_manage/excel/request"
  7. "eta_gn/eta_api/services/data"
  8. "eta_gn/eta_api/utils"
  9. "fmt"
  10. "sort"
  11. "strconv"
  12. "strings"
  13. "time"
  14. "github.com/shopspring/decimal"
  15. "github.com/yidane/formula"
  16. )
  17. type BaseCalculate struct {
  18. DataList []*data_manage.EdbDataList
  19. Frequency string `description:"需要转换的频度"`
  20. Formula interface{}
  21. Calendar string `description:"公历/农历"`
  22. MoveType int `description:"移动方式:1:领先(默认),2:滞后"`
  23. MoveFrequency string `description:"移动频度"`
  24. FromFrequency string `description:"来源的频度"`
  25. Source int `description:"1:累计值转月;2:累计值转季;3:同比值;4:同差值;5:N数值移动平均数计算;6:环比值;7:环差值;8:升频;9:降频;10:时间移位;11:超季节性;12:年化;13:累计值;14:累计值年初至今;15:指数修匀;16:日均值"`
  26. }
  27. type Cell struct {
  28. Column int `description:"行"`
  29. Row int `description:"列"`
  30. CellInfo request.MixedTableCellDataReq `description:"对应的单元格信息"`
  31. }
  32. func GetMixedTableCellData(mixedTableReq request.MixedTableReq, lang string) (newMixedTableCellDataList [][]request.MixedTableCellDataReq, err error, errMsg string) {
  33. cellRelationConf := mixedTableReq.CellRelation
  34. config := mixedTableReq.Data
  35. cellRelationConfMap := make(map[string]request.CellRelationConf)
  36. cellRelationConfList := make([]request.CellRelationConf, 0)
  37. if cellRelationConf != `` {
  38. err = json.Unmarshal([]byte(cellRelationConf), &cellRelationConfList)
  39. if err != nil {
  40. return
  41. }
  42. for _, v := range cellRelationConfList {
  43. cellRelationConfMap[v.Key] = v
  44. }
  45. }
  46. config, edbInfoIdList, _, err, errMsg := handleConfig(config)
  47. if err != nil {
  48. return
  49. }
  50. edbInfoList, err := data_manage.GetEdbInfoByIdList(edbInfoIdList)
  51. if err != nil {
  52. return
  53. }
  54. edbInfoMap := make(map[int]*data_manage.EdbInfo)
  55. edbDayDataListMap := make(map[int]map[string]float64)
  56. edbMonthDataListMap := make(map[int]map[string]string)
  57. edbDataListMap := make(map[int][]*data_manage.EdbDataList)
  58. for _, edbInfo := range edbInfoList {
  59. edbInfoMap[edbInfo.EdbInfoId] = edbInfo
  60. dataList := make([]*data_manage.EdbDataList, 0)
  61. switch edbInfo.EdbInfoType {
  62. case 0:
  63. dataList, _ = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.SubSource, edbInfo.EdbInfoId, ``, ``)
  64. case 1:
  65. _, dataList, _, _, _, _ = data.GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, ``, ``, false)
  66. default:
  67. err = errors.New(fmt.Sprint("获取失败,指标类型异常", edbInfo.EdbInfoType))
  68. }
  69. dateValMap := make(map[string]float64)
  70. monthDateMap := make(map[string]string)
  71. for _, tmpData := range dataList {
  72. dateValMap[tmpData.DataTime] = tmpData.Value
  73. yearMonth := strings.Join(strings.Split(tmpData.DataTime, "-")[0:2], "-")
  74. if _, ok := monthDateMap[yearMonth]; !ok {
  75. monthDateMap[yearMonth] = tmpData.DataTime
  76. }
  77. }
  78. edbDayDataListMap[edbInfo.EdbInfoId] = dateValMap
  79. edbMonthDataListMap[edbInfo.EdbInfoId] = monthDateMap
  80. edbDataListMap[edbInfo.EdbInfoId] = dataList
  81. }
  82. cellDataRelationMap := make(map[string]request.MixedTableCellDataReq, 0)
  83. for k, row := range config {
  84. for i, cell := range row {
  85. if cell.DataType == request.DateDT && cell.DataTimeType == request.EdbDateDT {
  86. var edbDateConfig request.EdbDateConf
  87. err = json.Unmarshal([]byte(cell.Value), &edbDateConfig)
  88. if err != nil {
  89. return
  90. }
  91. if dataList, ok := edbDataListMap[edbDateConfig.EdbInfoId]; ok {
  92. var newDate string
  93. newDate, err = GetEdbDateByMoveForward(config[k][i].Value, dataList)
  94. if err != nil {
  95. return
  96. }
  97. newDate, err = HandleMixTableDateChange(newDate, config[k][i].Value)
  98. if err != nil {
  99. return
  100. }
  101. cell.ShowValue = newDate
  102. cell.DataTime = newDate
  103. config[k][i] = cell
  104. }
  105. }
  106. row[i] = cell
  107. cellDataRelationMap[cell.Uid] = cell
  108. }
  109. config[k] = row
  110. }
  111. edbSourceDataMap := make(map[string]data.BaseCalculateDataResp)
  112. cellKeyVal := make(map[string]float64)
  113. calculateCellMap := make(map[string]Cell)
  114. calculateChainList := make([]string, 0)
  115. dateCalculateList := make([]string, 0)
  116. showStyleList := make([]string, 0)
  117. for k, row := range config {
  118. for i, cell := range row {
  119. switch cell.DataType {
  120. case request.EdbDT: // 指标类型
  121. if cell.Value == `` {
  122. if edbInfo, ok := edbInfoMap[cell.EdbInfoId]; ok {
  123. cell.ShowValue = edbInfo.EdbName
  124. }
  125. } else {
  126. cell.ShowValue = cell.Value
  127. }
  128. case request.InsertDataDT, request.PopInsertDataDT: // 数据类型
  129. cell.ShowValue = ``
  130. if relationConf, ok := cellRelationConfMap[cell.Uid]; ok { //表示表格日期
  131. if relationConf.RelationDate.Key == `` {
  132. continue
  133. }
  134. relationCell, ok := cellDataRelationMap[relationConf.RelationDate.Key]
  135. if !ok {
  136. continue
  137. }
  138. tmpDateValMap := make(map[string]float64)
  139. if dateValMap, ok := edbDayDataListMap[cell.EdbInfoId]; ok {
  140. tmpDateValMap = dateValMap
  141. }
  142. relationDate := relationCell.DataTime
  143. if strings.Contains(cell.Value, "{") {
  144. relationDate, err = HandleMixTableDateChange(relationDate, cell.Value)
  145. if err != nil {
  146. return
  147. }
  148. } else {
  149. cell.Value = ""
  150. }
  151. if val, ok2 := tmpDateValMap[relationDate]; ok2 {
  152. cellKeyVal[cell.Uid] = val
  153. cell.ShowValue = utils.FormatMixTableDataShowValue(val)
  154. }
  155. } else {
  156. if cell.DataTime == `` {
  157. if dateValList, ok := edbDataListMap[cell.EdbInfoId]; ok {
  158. tmpLenData := len(dateValList)
  159. if tmpLenData > 0 {
  160. if !strings.Contains(cell.Value, "{") {
  161. cell.Value = ""
  162. }
  163. var newDate string
  164. newDate, err = GetEdbDateByMoveForward(cell.Value, dateValList)
  165. if err != nil {
  166. return
  167. }
  168. newDate, err = HandleMixTableDateChange(newDate, cell.Value)
  169. if err != nil {
  170. return
  171. }
  172. var finalVal string
  173. for _, v := range dateValList {
  174. if v.DataTime == newDate {
  175. finalVal = utils.FormatMixTableDataShowValue(v.Value)
  176. cellKeyVal[cell.Uid] = v.Value
  177. break
  178. }
  179. }
  180. cell.ShowValue = finalVal
  181. }
  182. }
  183. } else {
  184. tmpDateList := strings.Split(cell.DataTime, "-")
  185. tmpDateValMap := make(map[string]float64)
  186. var newDate string
  187. if len(tmpDateList) == 2 {
  188. if dateMap, ok1 := edbMonthDataListMap[cell.EdbInfoId]; ok1 {
  189. if d, ok2 := dateMap[cell.DataTime]; ok2 {
  190. newDate = d
  191. }
  192. }
  193. } else {
  194. newDate = cell.DataTime
  195. }
  196. if !strings.Contains(cell.Value, "{") {
  197. cell.Value = ""
  198. }
  199. newDate, err = HandleMixTableDateChange(newDate, cell.Value)
  200. if err != nil {
  201. return
  202. }
  203. if dateValMap, ok3 := edbDayDataListMap[cell.EdbInfoId]; ok3 {
  204. tmpDateValMap = dateValMap
  205. if val, ok2 := tmpDateValMap[cell.DataTime]; ok2 {
  206. cellKeyVal[cell.Uid] = val
  207. cell.ShowValue = utils.FormatMixTableDataShowValue(val)
  208. }
  209. }
  210. }
  211. }
  212. case request.CustomTextDT: //自定义文本
  213. if cell.Value == `` {
  214. continue
  215. }
  216. tmpDeci, tmpErr := decimal.NewFromString(cell.Value)
  217. if tmpErr == nil {
  218. tmpVal, _ := tmpDeci.Float64()
  219. cellKeyVal[cell.Uid] = tmpVal
  220. }
  221. case request.FormulateCalculateDataDT: // 公式计算(A+B这种)
  222. calculateChainList = append(calculateChainList, cell.Uid)
  223. case request.InsertEdbCalculateDataDT: // 插入指标系统计算公式生成的值
  224. if !strings.Contains(cell.Value, "EdbInfoId") && cell.EdbInfoId > 0 {
  225. cell.Value, _ = fixCalculateValueConfig(cell.Value, cell.EdbInfoId)
  226. row[i] = cell
  227. }
  228. var cellDateTime string
  229. if relationConf, ok := cellRelationConfMap[cell.Uid]; ok {
  230. if relationConf.RelationDate.Key == `` {
  231. continue
  232. }
  233. relationCell, ok := cellDataRelationMap[relationConf.RelationDate.Key]
  234. if !ok {
  235. continue
  236. }
  237. cellDateTime = relationCell.DataTime
  238. }
  239. var tmpDataMap map[string]float64
  240. key := utils.MD5(cell.Value)
  241. respItemData, ok := edbSourceDataMap[key]
  242. if !ok {
  243. var tmpConfig request.CalculateConf
  244. err = json.Unmarshal([]byte(cell.Value), &tmpConfig)
  245. if err != nil {
  246. return
  247. }
  248. tmpDataList, ok := edbDataListMap[tmpConfig.EdbInfoId]
  249. if !ok {
  250. continue
  251. }
  252. edbInfo, ok := edbInfoMap[tmpConfig.EdbInfoId]
  253. if !ok {
  254. continue
  255. }
  256. req2 := &BaseCalculate{
  257. DataList: tmpDataList,
  258. Frequency: tmpConfig.Frequency,
  259. Formula: tmpConfig.Formula,
  260. Calendar: tmpConfig.Calendar,
  261. MoveType: tmpConfig.MoveType,
  262. MoveFrequency: tmpConfig.MoveFrequency,
  263. FromFrequency: edbInfo.Frequency,
  264. Source: tmpConfig.Source,
  265. }
  266. reqJson, tmpErr := json.Marshal(req2)
  267. if tmpErr != nil {
  268. utils.FileLog.Error(fmt.Sprintf("计算失败1,配置信息;%s;错误原因:%s", cell.Value, tmpErr.Error()))
  269. err = tmpErr
  270. return
  271. }
  272. respItem, tmpErr := data.BaseCalculate(string(reqJson), lang)
  273. if tmpErr != nil {
  274. utils.FileLog.Error(fmt.Sprintf("计算失败2,配置信息;%s;错误原因:%s", cell.Value, tmpErr.Error()))
  275. err = tmpErr
  276. return
  277. }
  278. if respItem.Ret != 200 {
  279. utils.FileLog.Error(fmt.Sprintf("计算失败3,配置信息;%s;原因:%s;错误原因:%s", cell.Value, respItem.Msg, respItem.ErrMsg))
  280. continue
  281. }
  282. edbSourceDataMap[key] = respItem.Data
  283. respItemData = respItem.Data
  284. }
  285. lenDataList := len(respItemData.DateList)
  286. tmpDataMap = respItemData.DataMap
  287. if cellDateTime == `` && lenDataList > 0 {
  288. cellDateTime = respItemData.DateList[lenDataList-1]
  289. cellDateTime, err = GetEdbDateByMoveForwardByDateList(cell.Value, respItemData.DateList)
  290. if err != nil {
  291. utils.FileLog.Error(fmt.Sprintf("日期前移失败,配置信息;%s", cell.Value))
  292. continue
  293. }
  294. }
  295. cellDateTime, err = HandleMixTableDateChange(cellDateTime, cell.Value)
  296. if err != nil {
  297. utils.FileLog.Error(fmt.Sprintf("日期变换失败,配置信息;%s, 日期:%s", cell.Value, cellDateTime))
  298. continue
  299. }
  300. val, ok := tmpDataMap[cellDateTime]
  301. if ok {
  302. cellKeyVal[cell.Uid] = val
  303. cell.ShowValue = utils.FormatMixTableDataShowValue(val)
  304. } else {
  305. cell.ShowValue = ""
  306. }
  307. case request.DateCalculateDataDT: //日期计算
  308. dateCalculateList = append(dateCalculateList, cell.Uid)
  309. }
  310. row[i] = cell
  311. }
  312. config[k] = row
  313. }
  314. for k, row := range config {
  315. for i, cell := range row {
  316. calculateCellMap[cell.Uid] = Cell{
  317. Column: k,
  318. Row: i,
  319. CellInfo: cell,
  320. }
  321. cell.ShowFormatValue = cell.ShowValue
  322. if cell.ShowStyle != `` {
  323. showStyleList = append(showStyleList, cell.Uid)
  324. }
  325. row[i] = cell
  326. cellDataRelationMap[cell.Uid] = cell
  327. }
  328. config[k] = row
  329. }
  330. if len(calculateChainList) > 0 {
  331. for _, cellKey := range calculateChainList {
  332. cellPosition, ok := calculateCellMap[cellKey]
  333. if !ok {
  334. utils.FileLog.Error("找不到单元格位置:", cellKey)
  335. continue
  336. }
  337. cell := config[cellPosition.Column][cellPosition.Row]
  338. if cell.DataType != request.FormulateCalculateDataDT { // 判断公式计算(A+B这种)类型,不是的话也过滤了
  339. continue
  340. }
  341. val, has, tmpErr, tmpErrMsg := getCalculateValueByCell(calculateCellMap, cellKey, cellKeyVal)
  342. if tmpErr != nil {
  343. errMsg = tmpErrMsg
  344. err = tmpErr
  345. return
  346. }
  347. if !has {
  348. continue
  349. }
  350. cellKeyVal[cell.Uid] = val
  351. cell.ShowValue = utils.FormatMixTableDataShowValue(val)
  352. config[cellPosition.Column][cellPosition.Row] = cell
  353. }
  354. }
  355. config, err, errMsg = handlerDateCalculate(dateCalculateList, calculateCellMap, config)
  356. if err != nil {
  357. return
  358. }
  359. config, err, errMsg = handleMixCellShowStyle(showStyleList, calculateCellMap, config)
  360. if err != nil {
  361. return
  362. }
  363. newMixedTableCellDataList = config
  364. return
  365. }
  366. func getCalculateValueByCell(calculateCellMap map[string]Cell, key string, cellKeyValMap map[string]float64) (val float64, has bool, err error, errMsg string) {
  367. val, ok := cellKeyValMap[key]
  368. if ok {
  369. has = true
  370. return
  371. }
  372. cell, ok := calculateCellMap[key]
  373. if !ok {
  374. err = errors.New("查找单元格" + key + "的数据失败")
  375. return
  376. }
  377. colData := cell.CellInfo
  378. if colData.DataType != request.FormulateCalculateDataDT {
  379. return
  380. }
  381. tagList := make([]utils.CellPosition, 0)
  382. var relationCellList []request.RelationCell
  383. if colData.Extra == `` {
  384. err = errors.New(colData.Uid + "没有绑定关系")
  385. return
  386. }
  387. err = json.Unmarshal([]byte(colData.Extra), &relationCellList)
  388. if err != nil {
  389. return
  390. }
  391. for _, relation := range relationCellList {
  392. tmpVal, _, tmpErr, tmpErrMsg := getCalculateValueByCell(calculateCellMap, relation.Key, cellKeyValMap)
  393. if tmpErr != nil {
  394. errMsg = tmpErrMsg
  395. err = tmpErr
  396. return
  397. }
  398. cellKeyValMap[relation.Key] = tmpVal
  399. rowInt, tmpErr := strconv.Atoi(relation.Row)
  400. if tmpErr != nil {
  401. err = tmpErr
  402. return
  403. }
  404. tagList = append(tagList, utils.CellPosition{
  405. Tag: relation.Tag,
  406. Row: rowInt,
  407. Value: tmpVal,
  408. })
  409. }
  410. val, errMsg, err = calculateByCellList(strings.ToUpper(colData.Value), tagList)
  411. if err != nil {
  412. return
  413. }
  414. has = true
  415. cellKeyValMap[key] = val
  416. return
  417. }
  418. func handleConfig(configList [][]request.MixedTableCellDataReq) (newConfig [][]request.MixedTableCellDataReq, edbInfoIdList []int, dataEdbInfoIdList []int, err error, errMsg string) {
  419. edbInfoIdList = make([]int, 0)
  420. dataEdbInfoIdList = make([]int, 0)
  421. for ck, rowList := range configList {
  422. for rk, cell := range rowList {
  423. switch cell.DataType {
  424. case request.EdbDT: // 指标信息
  425. edbInfoIdList = append(edbInfoIdList, cell.EdbInfoId)
  426. case request.InsertDataDT, request.PopInsertDataDT: // 插值、弹框插值
  427. dataEdbInfoIdList = append(dataEdbInfoIdList, cell.EdbInfoId)
  428. edbInfoIdList = append(edbInfoIdList, cell.EdbInfoId)
  429. case request.InsertEdbCalculateDataDT: // 插入指标计算公式生成的值
  430. var config request.CalculateConf
  431. err = json.Unmarshal([]byte(cell.Value), &config)
  432. if err != nil {
  433. return
  434. }
  435. if config.EdbInfoId == 0 && cell.EdbInfoId > 0 {
  436. edbInfoIdList = append(edbInfoIdList, cell.EdbInfoId)
  437. } else {
  438. edbInfoIdList = append(edbInfoIdList, config.EdbInfoId)
  439. }
  440. dataEdbInfoIdList = append(dataEdbInfoIdList, cell.EdbInfoId)
  441. case request.DateDT: // 日期类型
  442. date, newVal, tmpErr, tmpErrMsg := handleDate(cell.DataTimeType, cell.Value)
  443. if tmpErr != nil {
  444. err = tmpErr
  445. errMsg = tmpErrMsg
  446. return
  447. }
  448. rowList[rk].DataTime = date
  449. rowList[rk].ShowValue = date
  450. rowList[rk].Value = newVal //兼容原有的历史数据中系统导入日期
  451. if cell.DataTimeType == request.EdbDateDT {
  452. var config request.EdbDateConf
  453. err = json.Unmarshal([]byte(cell.Value), &config)
  454. if err != nil {
  455. return
  456. }
  457. edbInfoIdList = append(edbInfoIdList, config.EdbInfoId)
  458. }
  459. }
  460. }
  461. configList[ck] = rowList
  462. }
  463. newConfig = configList
  464. return
  465. }
  466. func HandleDate(dataTimeType int, val string) (date string, newVal string, err error, errMsg string) {
  467. return handleDate(dataTimeType, val)
  468. }
  469. func handleDate(dataTimeType int, val string) (date string, newVal string, err error, errMsg string) {
  470. newVal = val
  471. if val == `` {
  472. errMsg = "错误的日期数据"
  473. err = errors.New(errMsg)
  474. return
  475. }
  476. switch dataTimeType {
  477. case request.CustomDateT: //手动输入日期
  478. date = val
  479. return
  480. case request.SystemDateT: // 系统日期
  481. date = time.Now().Format(utils.FormatDate)
  482. newVal, err, errMsg = handleOldSystemDateT(val)
  483. if err != nil {
  484. return
  485. }
  486. date, err = HandleMixTableDateChange(date, newVal)
  487. if err != nil {
  488. return
  489. }
  490. case request.EdbDateDT: // 导入指标日期(指标库的最新日期)
  491. default:
  492. errMsg = "错误的日期类型"
  493. err = errors.New(errMsg)
  494. return
  495. }
  496. return
  497. }
  498. func GetEdbDateByMoveForward(conf string, edbDataList []*data_manage.EdbDataList) (date string, err error) {
  499. dateList := make([]string, 0)
  500. for _, v := range edbDataList {
  501. dateList = append(dateList, v.DataTime)
  502. }
  503. date, err = GetEdbDateByMoveForwardByDateList(conf, dateList)
  504. return
  505. }
  506. func GetEdbDateByMoveForwardByDateList(conf string, dateList []string) (date string, err error) {
  507. moveForward := 0
  508. if conf != "" {
  509. var edbDateConf request.EdbDateChangeConf
  510. err = json.Unmarshal([]byte(conf), &edbDateConf)
  511. if err != nil {
  512. err = fmt.Errorf("日期变换配置json解析失败失败: %s", err.Error())
  513. return
  514. }
  515. moveForward = edbDateConf.MoveForward
  516. }
  517. index := len(dateList) - 1 - moveForward
  518. for k, v := range dateList {
  519. if k == index {
  520. date = v
  521. return
  522. }
  523. }
  524. return
  525. }
  526. func HandleMixTableDateChange(date, conf string) (newDate string, err error) {
  527. newDate = date
  528. if conf == "" {
  529. return
  530. }
  531. var edbDateConf request.EdbDateConf
  532. err = json.Unmarshal([]byte(conf), &edbDateConf)
  533. if err != nil {
  534. err = fmt.Errorf("日期变换配置json解析失败失败: %s, Err:%s", conf, err.Error())
  535. return
  536. }
  537. if newDate != "" {
  538. if len(edbDateConf.DateChange) > 0 {
  539. var dateTime time.Time
  540. dateTime, err = time.ParseInLocation(utils.FormatDate, newDate, time.Local)
  541. if err != nil {
  542. err = fmt.Errorf("日期解析失败: %s", err.Error())
  543. return
  544. }
  545. for _, v := range edbDateConf.DateChange {
  546. if v.ChangeType == 1 {
  547. dateTime = dateTime.AddDate(v.Year, v.Month, v.Day)
  548. newDate = dateTime.Format(utils.FormatDate)
  549. } else if v.ChangeType == 2 {
  550. newDate, err, _ = HandleSystemAppointDateT(dateTime, v.FrequencyDay, v.Frequency)
  551. if err != nil {
  552. return
  553. }
  554. dateTime, err = time.ParseInLocation(utils.FormatDate, newDate, time.Local)
  555. if err != nil {
  556. err = fmt.Errorf("日期解析失败: %s", err.Error())
  557. return
  558. }
  559. }
  560. }
  561. }
  562. }
  563. return
  564. }
  565. func handleOldSystemDateT(confStr string) (newConf string, err error, errMsg string) {
  566. newConf = confStr
  567. var config request.SystemDateConf
  568. err = json.Unmarshal([]byte(confStr), &config)
  569. if err != nil {
  570. return
  571. }
  572. newConfig := new(request.EdbDateConf)
  573. dateChange := new(request.EdbDateConfDateChange)
  574. dateChangeList := make([]*request.EdbDateConfDateChange, 0)
  575. switch config.Source {
  576. case request.SystemCurrDateT:
  577. return
  578. case request.SystemCalculateDateT:
  579. dateChange.Day = config.CalculateNum
  580. dateChange.ChangeType = 1
  581. dateChangeList = append(dateChangeList, dateChange)
  582. newConfig.DateChange = dateChangeList
  583. newConfByte, e := json.Marshal(newConfig)
  584. if e != nil {
  585. err = fmt.Errorf("日期计算额外配置,json序列化失败: %s", e.Error())
  586. return
  587. }
  588. newConf = string(newConfByte)
  589. return
  590. case request.SystemFrequencyDateT: // 处理系统日期相关的指定频率(所在周/旬/月/季/半年/年的最后/最早一天)
  591. dateChange.FrequencyDay = config.Day
  592. dateChange.Frequency = config.Frequency
  593. dateChange.ChangeType = 1
  594. dateChangeList = append(dateChangeList, dateChange)
  595. newConfig.DateChange = dateChangeList
  596. newConfByte, e := json.Marshal(newConfig)
  597. if e != nil {
  598. err = fmt.Errorf("日期计算额外配置,json序列化失败: %s", e.Error())
  599. return
  600. }
  601. newConf = string(newConfByte)
  602. return
  603. default:
  604. return
  605. }
  606. return
  607. }
  608. func HandleSystemAppointDateT(currDate time.Time, appointDay, frequency string) (date string, err error, errMsg string) {
  609. switch frequency {
  610. case "本周":
  611. day := int(currDate.Weekday())
  612. if day == 0 { // 周日
  613. day = 7
  614. }
  615. num := 0
  616. switch appointDay {
  617. case "周一":
  618. num = 1
  619. case "周二":
  620. num = 2
  621. case "周三":
  622. num = 3
  623. case "周四":
  624. num = 4
  625. case "周五":
  626. num = 5
  627. case "周六":
  628. num = 6
  629. case "周日":
  630. num = 7
  631. }
  632. day = num - day
  633. date = currDate.AddDate(0, 0, day).Format(utils.FormatDate)
  634. case "本旬":
  635. day := currDate.Day()
  636. var tmpDate time.Time
  637. switch appointDay {
  638. case "第一天":
  639. if day <= 10 {
  640. tmpDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, currDate.Location())
  641. } else if day <= 20 {
  642. tmpDate = time.Date(currDate.Year(), currDate.Month(), 11, 0, 0, 0, 0, currDate.Location())
  643. } else {
  644. tmpDate = time.Date(currDate.Year(), currDate.Month(), 21, 0, 0, 0, 0, currDate.Location())
  645. }
  646. case "最后一天":
  647. if day <= 10 {
  648. tmpDate = time.Date(currDate.Year(), currDate.Month(), 10, 0, 0, 0, 0, currDate.Location())
  649. } else if day <= 20 {
  650. tmpDate = time.Date(currDate.Year(), currDate.Month(), 20, 0, 0, 0, 0, currDate.Location())
  651. } else {
  652. tmpDate = time.Date(currDate.Year(), currDate.Month()+1, 1, 0, 0, 0, 0, currDate.Location()).AddDate(0, 0, -1)
  653. }
  654. }
  655. date = tmpDate.Format(utils.FormatDate)
  656. case "本月":
  657. var tmpDate time.Time
  658. switch appointDay {
  659. case "第一天":
  660. tmpDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, currDate.Location())
  661. case "最后一天":
  662. tmpDate = time.Date(currDate.Year(), currDate.Month()+1, 1, 0, 0, 0, 0, currDate.Location()).AddDate(0, 0, -1)
  663. }
  664. date = tmpDate.Format(utils.FormatDate)
  665. case "本季":
  666. month := currDate.Month()
  667. var tmpDate time.Time
  668. switch appointDay {
  669. case "第一天":
  670. if month <= 3 {
  671. tmpDate = time.Date(currDate.Year(), 1, 1, 0, 0, 0, 0, currDate.Location())
  672. } else if month <= 6 {
  673. tmpDate = time.Date(currDate.Year(), 4, 1, 0, 0, 0, 0, currDate.Location())
  674. } else if month <= 9 {
  675. tmpDate = time.Date(currDate.Year(), 7, 1, 0, 0, 0, 0, currDate.Location())
  676. } else {
  677. tmpDate = time.Date(currDate.Year(), 10, 1, 0, 0, 0, 0, currDate.Location())
  678. }
  679. case "最后一天":
  680. if month <= 3 {
  681. tmpDate = time.Date(currDate.Year(), 3, 31, 0, 0, 0, 0, currDate.Location())
  682. } else if month <= 6 {
  683. tmpDate = time.Date(currDate.Year(), 6, 30, 0, 0, 0, 0, currDate.Location())
  684. } else if month <= 9 {
  685. tmpDate = time.Date(currDate.Year(), 9, 30, 0, 0, 0, 0, currDate.Location())
  686. } else {
  687. tmpDate = time.Date(currDate.Year(), 12, 31, 0, 0, 0, 0, currDate.Location())
  688. }
  689. }
  690. date = tmpDate.Format(utils.FormatDate)
  691. case "本半年":
  692. month := currDate.Month()
  693. var tmpDate time.Time
  694. switch appointDay {
  695. case "第一天":
  696. if month <= 6 {
  697. tmpDate = time.Date(currDate.Year(), 1, 1, 0, 0, 0, 0, currDate.Location())
  698. } else {
  699. tmpDate = time.Date(currDate.Year(), 7, 1, 0, 0, 0, 0, currDate.Location())
  700. }
  701. case "最后一天":
  702. if month <= 6 {
  703. tmpDate = time.Date(currDate.Year(), 6, 30, 0, 0, 0, 0, currDate.Location())
  704. } else {
  705. tmpDate = time.Date(currDate.Year(), 12, 31, 0, 0, 0, 0, currDate.Location())
  706. }
  707. }
  708. date = tmpDate.Format(utils.FormatDate)
  709. case "本年":
  710. var tmpDate time.Time
  711. switch appointDay {
  712. case "第一天":
  713. tmpDate = time.Date(currDate.Year(), 1, 1, 0, 0, 0, 0, currDate.Location())
  714. case "最后一天":
  715. tmpDate = time.Date(currDate.Year(), 12, 31, 0, 0, 0, 0, currDate.Location())
  716. }
  717. date = tmpDate.Format(utils.FormatDate)
  718. default:
  719. errMsg = "错误的日期频度:" + frequency
  720. err = errors.New(errMsg)
  721. return
  722. }
  723. return
  724. }
  725. func calculateByCellList(calculateFormula string, tagList []utils.CellPosition) (calVal float64, errMsg string, err error) {
  726. if calculateFormula == "" {
  727. errMsg = "公式异常"
  728. err = errors.New(errMsg)
  729. return
  730. }
  731. calculateFormula = strings.TrimPrefix(calculateFormula, "=")
  732. calculateFormula = strings.Replace(calculateFormula, "(", "(", -1)
  733. calculateFormula = strings.Replace(calculateFormula, ")", ")", -1)
  734. calculateFormula = strings.Replace(calculateFormula, ",", ",", -1)
  735. calculateFormula = strings.Replace(calculateFormula, "。", ".", -1)
  736. calculateFormula = strings.Replace(calculateFormula, "%", "*0.01", -1)
  737. rowList := make([]int, 0)
  738. rowListMap := make(map[int][]utils.CellPosition)
  739. for _, v := range tagList {
  740. tmpRowList, ok := rowListMap[v.Row]
  741. if !ok {
  742. rowList = append(rowList, v.Row)
  743. tmpRowList = make([]utils.CellPosition, 0)
  744. }
  745. tmpRowList = append(tmpRowList, v)
  746. rowListMap[v.Row] = tmpRowList
  747. }
  748. sort.Ints(rowList)
  749. list := make([]utils.CellPosition, 0)
  750. for _, row := range rowList {
  751. list = append(list, rowListMap[row]...)
  752. }
  753. formulaFormStr := utils.ReplaceFormulaByCellList(list, calculateFormula)
  754. if formulaFormStr == `` {
  755. errMsg = "公式异常"
  756. err = errors.New(errMsg)
  757. return
  758. }
  759. expression := formula.NewExpression(formulaFormStr)
  760. calResult, err := expression.Evaluate()
  761. if err != nil {
  762. errMsg = "计算失败"
  763. err = errors.New("计算失败:Err:" + err.Error() + ";formulaStr:" + formulaFormStr)
  764. if strings.Contains(err.Error(), "divide by zero") {
  765. errMsg = "分母不能为0"
  766. err = errors.New("分母不能为空,计算公式:" + formulaFormStr)
  767. }
  768. return
  769. }
  770. if calResult.IsNan() {
  771. errMsg = "计算失败"
  772. err = errors.New("计算失败:计算结果是:NAN;formulaStr:" + formulaFormStr)
  773. return
  774. }
  775. calVal, err = calResult.Float64()
  776. if err != nil {
  777. return
  778. }
  779. calVal, _ = decimal.NewFromFloat(calVal).Round(4).Float64()
  780. return
  781. }
  782. func handlerDateCalculate(dateCalculateList []string, calculateCellMap map[string]Cell, oldConfig [][]request.MixedTableCellDataReq) (config [][]request.MixedTableCellDataReq, err error, errMsg string) {
  783. config = oldConfig
  784. if len(dateCalculateList) == 0 {
  785. return
  786. }
  787. if len(dateCalculateList) > 0 {
  788. for _, cellKey := range dateCalculateList {
  789. cellPosition, ok := calculateCellMap[cellKey]
  790. if !ok {
  791. utils.FileLog.Error("找不到单元格位置:", cellKey)
  792. continue
  793. }
  794. cell := config[cellPosition.Column][cellPosition.Row]
  795. if cell.DataType != request.DateCalculateDataDT { // 判断公式计算(A+B这种)类型,不是的话也过滤了
  796. continue
  797. }
  798. val, tmpErr, tmpErrMsg := DateCalculatePrepare(calculateCellMap, cell.Value)
  799. if tmpErr != nil {
  800. cell.ShowValue = ""
  801. config[cellPosition.Column][cellPosition.Row] = cell
  802. utils.FileLog.Error(fmt.Sprintf("%s 日期计算报错:Err:%s:%s", cellKey, tmpErr, tmpErrMsg))
  803. continue
  804. }
  805. cell.ShowValue = utils.FormatMixTableDataShowValue(val)
  806. config[cellPosition.Column][cellPosition.Row] = cell
  807. }
  808. }
  809. return
  810. }
  811. func DateCalculatePrepare(calculateCellMap map[string]Cell, config string) (val float64, err error, errMsg string) {
  812. var edbDateConf request.MixDateCalculateConf
  813. err = json.Unmarshal([]byte(config), &edbDateConf)
  814. if err != nil {
  815. err = fmt.Errorf("日期计算配置json解析失败失败: %s, Err:%s", config, err.Error())
  816. return
  817. }
  818. if len(edbDateConf.RelationCellList) == 0 {
  819. err = fmt.Errorf("日期计算 未配置日期单元格失败: %s", config)
  820. return
  821. }
  822. valMap := make(map[string]int)
  823. for _, v := range edbDateConf.RelationCellList {
  824. cell, ok := calculateCellMap[v.Uid]
  825. if !ok {
  826. err = fmt.Errorf("查找单元格:%s 的数据失败", v.Uid)
  827. return
  828. }
  829. colData := cell.CellInfo
  830. _, err = time.ParseInLocation(utils.FormatDate, colData.ShowValue, time.Local)
  831. if err != nil {
  832. err = fmt.Errorf("%s 的单元格非日期类型, Err: %s", colData.ShowValue, err.Error())
  833. return
  834. }
  835. realDiffDay := utils.GetDaysDiff1900(colData.ShowValue)
  836. valMap[strings.ToUpper(v.Tag)] = realDiffDay
  837. }
  838. val, errMsg, err = DateCalculateFormula(valMap, strings.ToUpper(edbDateConf.Formula))
  839. if err != nil {
  840. return
  841. }
  842. return
  843. }
  844. func DateCalculateFormula(valTagMap map[string]int, calculateFormula string) (calVal float64, errMsg string, err error) {
  845. if calculateFormula == "" {
  846. errMsg = "公式异常"
  847. err = errors.New(errMsg)
  848. return
  849. }
  850. calculateFormula = strings.TrimPrefix(calculateFormula, "=")
  851. calculateFormula = strings.Replace(calculateFormula, "(", "(", -1)
  852. calculateFormula = strings.Replace(calculateFormula, ")", ")", -1)
  853. calculateFormula = strings.Replace(calculateFormula, ",", ",", -1)
  854. calculateFormula = strings.Replace(calculateFormula, "。", ".", -1)
  855. calculateFormula = strings.Replace(calculateFormula, "%", "*0.01", -1)
  856. formulaFormStr := utils.ReplaceFormulaByTagMap(valTagMap, calculateFormula)
  857. if formulaFormStr == `` {
  858. errMsg = "公式异常"
  859. err = errors.New(errMsg)
  860. return
  861. }
  862. fmt.Println("公式:" + formulaFormStr)
  863. expression := formula.NewExpression(formulaFormStr)
  864. calResult, err := expression.Evaluate()
  865. if err != nil {
  866. errMsg = "公式错误,请重新填写"
  867. err = errors.New("计算失败:Err:" + err.Error() + ";formulaStr:" + formulaFormStr)
  868. if strings.Contains(err.Error(), "divide by zero") {
  869. errMsg = "分母不能为0"
  870. err = errors.New("分母不能为空,计算公式:" + formulaFormStr)
  871. }
  872. return
  873. }
  874. if calResult.IsNan() {
  875. errMsg = "公式错误,请重新填写"
  876. err = errors.New("计算失败:计算结果是:NAN;formulaStr:" + formulaFormStr)
  877. return
  878. }
  879. calVal, err = calResult.Float64()
  880. if err != nil {
  881. return
  882. }
  883. calVal, _ = decimal.NewFromFloat(calVal).Round(4).Float64()
  884. return
  885. }
  886. func handleMixCellShowStyle(showStyleList []string, calculateCellMap map[string]Cell, oldConfig [][]request.MixedTableCellDataReq) (config [][]request.MixedTableCellDataReq, err error, errMsg string) {
  887. config = oldConfig
  888. if len(showStyleList) == 0 {
  889. return
  890. }
  891. if len(showStyleList) > 0 {
  892. for _, cellKey := range showStyleList {
  893. cellPosition, ok := calculateCellMap[cellKey]
  894. if !ok {
  895. utils.FileLog.Error("找不到单元格位置:", cellKey)
  896. continue
  897. }
  898. cell := config[cellPosition.Column][cellPosition.Row]
  899. val := cell.ShowValue
  900. if cell.ShowValue == "" {
  901. _, err := strconv.ParseFloat(cell.Value, 64)
  902. if err == nil {
  903. val = cell.Value
  904. cell.ShowValue = cell.Value
  905. }
  906. }
  907. _, e := strconv.ParseFloat(val, 64) // 将字符串转换成float类型
  908. if e != nil { // 如果没有错误发生则返回true,说明该字符串是一个合法的数字
  909. var styleConf request.MixCellShowStyle
  910. err = json.Unmarshal([]byte(cell.ShowStyle), &styleConf)
  911. if err != nil {
  912. err = fmt.Errorf("日期计算配置json解析失败失败: %s, Err:%s", config, err.Error())
  913. return
  914. }
  915. if styleConf.GlObj != nil {
  916. styleConf.GlObj = nil
  917. tmpStyleConf, err := json.Marshal(styleConf)
  918. if err == nil {
  919. cell.ShowStyle = string(tmpStyleConf)
  920. }
  921. }
  922. config[cellPosition.Column][cellPosition.Row] = cell
  923. continue
  924. }
  925. var styleConf request.MixCellShowStyle
  926. err = json.Unmarshal([]byte(cell.ShowStyle), &styleConf)
  927. if err != nil {
  928. err = fmt.Errorf("日期计算配置json解析失败失败: %s, Err:%s", config, err.Error())
  929. return
  930. }
  931. hasPercent := false
  932. if styleConf.Nt == "percent" {
  933. hasPercent = true
  934. }
  935. if styleConf.Pn != 0 || styleConf.Nt != "" {
  936. if styleConf.Pn != 0 {
  937. if styleConf.Decimal == nil {
  938. styleConf.Decimal = new(int)
  939. }
  940. *styleConf.Decimal += styleConf.Pn
  941. if *styleConf.Decimal < 0 {
  942. *styleConf.Decimal = 0
  943. }
  944. cell.ShowFormatValue = utils.RoundNumber(cell.ShowValue, *styleConf.Decimal, hasPercent)
  945. styleConf.Pn = 0
  946. } else if styleConf.Decimal != nil {
  947. cell.ShowFormatValue = utils.RoundNumber(cell.ShowValue, *styleConf.Decimal, hasPercent)
  948. } else {
  949. if hasPercent {
  950. numDecimal, _ := decimal.NewFromString(cell.ShowValue)
  951. tmpStr := numDecimal.Mul(decimal.NewFromInt(100)).String()
  952. cell.ShowFormatValue = tmpStr + "%"
  953. } else {
  954. cell.ShowFormatValue = cell.ShowValue
  955. }
  956. }
  957. } else if styleConf.Decimal != nil {
  958. cell.ShowFormatValue = utils.RoundNumber(cell.ShowValue, *styleConf.Decimal, hasPercent)
  959. } else {
  960. cell.ShowFormatValue = cell.ShowValue
  961. }
  962. styleConf.GlObj = nil
  963. tmpStyleConf, err := json.Marshal(styleConf)
  964. if err == nil {
  965. cell.ShowStyle = string(tmpStyleConf)
  966. }
  967. config[cellPosition.Column][cellPosition.Row] = cell
  968. }
  969. }
  970. return
  971. }
  972. func changePointDecimalPlaces(str string, changeNum int, numberType string, isPercent bool) (newStr string) {
  973. newStr = str
  974. var decimalPlaces int
  975. dotIndex := strings.Index(newStr, ".") // 查找小数点的位置
  976. if dotIndex == -1 {
  977. decimalPlaces = 0
  978. } else {
  979. decimalPlaces = len(newStr) - dotIndex - 1
  980. }
  981. val, _ := strconv.ParseFloat(str, 64)
  982. if isPercent {
  983. if numberType == "number" { //百分数转成小数
  984. val = val / 100
  985. if decimalPlaces > 2 {
  986. decimalPlaces += 2
  987. } else if decimalPlaces == 1 {
  988. decimalPlaces += 1
  989. } else if decimalPlaces == 0 {
  990. if len(str) == 1 {
  991. decimalPlaces = 2
  992. } else if len(str) == 2 {
  993. if str[1] == '0' {
  994. decimalPlaces = 1
  995. } else {
  996. decimalPlaces = 2
  997. }
  998. }
  999. }
  1000. isPercent = false
  1001. }
  1002. } else {
  1003. if numberType == "percent" {
  1004. if decimalPlaces > 2 {
  1005. decimalPlaces -= 2
  1006. } else if decimalPlaces == 1 {
  1007. decimalPlaces = 0
  1008. }
  1009. val = val * 100
  1010. }
  1011. }
  1012. if decimalPlaces > 0 {
  1013. val, _ = decimal.NewFromFloat(val).Round(int32(decimalPlaces)).Float64()
  1014. newStr = strconv.FormatFloat(val, 'f', decimalPlaces, 64)
  1015. } else {
  1016. newStr = fmt.Sprintf("%.f", val)
  1017. }
  1018. decimalPlaces = 0
  1019. dotIndex = strings.Index(newStr, ".") // 查找小数点的位置
  1020. if dotIndex == -1 {
  1021. decimalPlaces = 0
  1022. } else {
  1023. decimalPlaces = len(newStr) - dotIndex - 1
  1024. }
  1025. decimalPlaces += changeNum
  1026. if decimalPlaces < 0 {
  1027. decimalPlaces = 0
  1028. }
  1029. val, _ = decimal.NewFromFloat(val).Round(int32(decimalPlaces)).Float64()
  1030. newStr = strconv.FormatFloat(val, 'f', decimalPlaces, 64)
  1031. if numberType == "percent" || isPercent {
  1032. newStr += "%"
  1033. }
  1034. return
  1035. }
  1036. func fixCalculateValueConfig(conf string, edbInfoId int) (newConf string, err error) {
  1037. newConf = conf
  1038. if edbInfoId == 0 {
  1039. return
  1040. }
  1041. var tmpConfig request.CalculateConf
  1042. err = json.Unmarshal([]byte(conf), &tmpConfig)
  1043. if err != nil {
  1044. return
  1045. }
  1046. if tmpConfig.EdbInfoId == 0 {
  1047. tmpConfig.EdbInfoId = edbInfoId
  1048. newConfByte, _ := json.Marshal(tmpConfig)
  1049. newConf = string(newConfByte)
  1050. return
  1051. }
  1052. return
  1053. }