predict_edb_info.go 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362
  1. package data
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "github.com/shopspring/decimal"
  7. "github.com/yidane/formula"
  8. "hongze/hz_crm_api/models/data_manage"
  9. "hongze/hz_crm_api/models/data_manage/request"
  10. "hongze/hz_crm_api/models/system"
  11. "hongze/hz_crm_api/utils"
  12. "strconv"
  13. "strings"
  14. "time"
  15. )
  16. // AddPredictEdbInfo 新增预测指标
  17. func AddPredictEdbInfo(sourceEdbInfoId, classifyId int, edbName string, ruleList []request.RuleConfig, sysUserId int, sysUserName, requestBody, requestUrl string) (edbInfo *data_manage.EdbInfo, err error, errMsg string) {
  18. var sourceEdbInfo *data_manage.EdbInfo
  19. // 来源指标信息校验
  20. {
  21. sourceEdbInfo, err = data_manage.GetEdbInfoById(sourceEdbInfoId)
  22. if err != nil && err.Error() != utils.ErrNoRow() {
  23. errMsg = "新增失败"
  24. err = errors.New("获取来源指标失败,Err:" + err.Error())
  25. return
  26. }
  27. if sourceEdbInfo == nil {
  28. errMsg = "找不到该来源指标"
  29. err = nil
  30. return
  31. }
  32. //必须是普通的指标
  33. if sourceEdbInfo.EdbInfoType != 0 {
  34. errMsg = "来源指标异常,不是普通的指标"
  35. return
  36. }
  37. if !utils.InArrayByStr([]string{"日度", "周度", "月度"}, sourceEdbInfo.Frequency) {
  38. errMsg = "预测指标只支持选择日度、周度、月度的指标"
  39. return
  40. }
  41. }
  42. var classifyInfo *data_manage.EdbClassify
  43. // 来源分类信息校验
  44. {
  45. classifyInfo, err = data_manage.GetEdbClassifyById(classifyId)
  46. if err != nil && err.Error() != utils.ErrNoRow() {
  47. errMsg = "新增失败"
  48. err = errors.New("获取预测指标分类失败,Err:" + err.Error())
  49. return
  50. }
  51. if classifyInfo == nil {
  52. errMsg = "找不到该预测指标分类"
  53. err = nil
  54. return
  55. }
  56. //必须是预测指标分类
  57. if classifyInfo.ClassifyType != 1 {
  58. errMsg = "预测指标分类异常,不是预测指标分类"
  59. return
  60. }
  61. }
  62. edbName = strings.Trim(edbName, " ")
  63. edbCode := sourceEdbInfo.EdbCode + "_" + time.Now().Format(utils.FormatShortDateTimeUnSpace)
  64. // 判断该来源指标是否已经被引用了
  65. {
  66. //predictEdbConf, tmpErr := data_manage.GetPredictEdbConfBySourceEdbInfoId(sourceEdbInfoId)
  67. //if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
  68. // errMsg = "新增失败"
  69. // err = tmpErr
  70. // return
  71. //}
  72. // 如果该来源指标已经被引用了,那么不允许再次使用
  73. //if predictEdbConf != nil {
  74. // //获取预测指标详情
  75. // predictEdbInfo, tmpErr := data_manage.GetEdbInfoById(predictEdbConf.PredictEdbInfoId)
  76. // if tmpErr != nil {
  77. // errMsg = "新增失败"
  78. // err = tmpErr
  79. // return
  80. // }
  81. // //获取预测指标的分类
  82. // edbClassifyInfo, tmpErr := data_manage.GetEdbClassifyById(predictEdbInfo.ClassifyId)
  83. // if tmpErr != nil {
  84. // errMsg = "新增失败"
  85. // err = tmpErr
  86. // return
  87. // }
  88. // errMsg = "该指标已存在数据库,目录为:" + edbClassifyInfo.ClassifyName + ",请重新选择指标"
  89. // err = errors.New(errMsg)
  90. // return
  91. //}
  92. }
  93. //判断指标名称是否存在
  94. var condition string
  95. var pars []interface{}
  96. condition += " AND edb_info_type=? "
  97. pars = append(pars, 1)
  98. condition += " AND edb_name=? "
  99. pars = append(pars, edbName)
  100. count, err := data_manage.GetEdbInfoCountByCondition(condition, pars)
  101. if err != nil {
  102. errMsg = "判断指标名称是否存在失败"
  103. err = errors.New("判断指标名称是否存在失败,Err:" + err.Error())
  104. return
  105. }
  106. if count > 0 {
  107. errMsg = "指标名称已存在,请重新填写"
  108. return
  109. }
  110. timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
  111. edbInfo = &data_manage.EdbInfo{
  112. //EdbInfoId: 0,
  113. EdbInfoType: 1,
  114. SourceName: "预测指标",
  115. Source: utils.DATA_SOURCE_PREDICT,
  116. EdbCode: edbCode,
  117. EdbName: edbName,
  118. EdbNameSource: edbName,
  119. Frequency: sourceEdbInfo.Frequency,
  120. Unit: sourceEdbInfo.Unit,
  121. StartDate: sourceEdbInfo.StartDate,
  122. ClassifyId: classifyId,
  123. SysUserId: sysUserId,
  124. SysUserRealName: sysUserName,
  125. UniqueCode: utils.MD5(utils.DATA_PREFIX + "_" + timestamp),
  126. CreateTime: time.Now(),
  127. ModifyTime: time.Now(),
  128. MinValue: sourceEdbInfo.MinValue,
  129. MaxValue: sourceEdbInfo.MaxValue,
  130. CalculateFormula: sourceEdbInfo.CalculateFormula,
  131. EdbType: 1,
  132. //Sort: sourceEdbInfo.,
  133. LatestDate: sourceEdbInfo.LatestDate,
  134. LatestValue: sourceEdbInfo.LatestValue,
  135. MoveType: sourceEdbInfo.MoveType,
  136. MoveFrequency: sourceEdbInfo.MoveFrequency,
  137. NoUpdate: sourceEdbInfo.NoUpdate,
  138. ServerUrl: "",
  139. }
  140. // 关联关系表
  141. calculateMappingList := make([]*data_manage.EdbInfoCalculateMapping, 0)
  142. fromEdbMap := make(map[int]int)
  143. // 源指标关联关系表
  144. calculateMappingItem := &data_manage.EdbInfoCalculateMapping{
  145. //EdbInfoCalculateMappingId: 0,
  146. //EdbInfoId: 0,
  147. Source: edbInfo.Source,
  148. SourceName: edbInfo.SourceName,
  149. EdbCode: edbInfo.EdbCode,
  150. FromEdbInfoId: sourceEdbInfo.EdbInfoId,
  151. FromEdbCode: sourceEdbInfo.EdbCode,
  152. FromEdbName: sourceEdbInfo.EdbName,
  153. FromSource: sourceEdbInfo.Source,
  154. FromSourceName: sourceEdbInfo.SourceName,
  155. //FromTag: "",
  156. Sort: 1,
  157. CreateTime: time.Now(),
  158. ModifyTime: time.Now(),
  159. }
  160. fromEdbMap[sourceEdbInfoId] = sourceEdbInfoId
  161. calculateMappingList = append(calculateMappingList, calculateMappingItem)
  162. // 预测指标配置
  163. predictEdbConfList := make([]*data_manage.PredictEdbConf, 0)
  164. for _, v := range ruleList {
  165. // 预测指标配置
  166. ruleEndDate, tmpErr := time.ParseInLocation(utils.FormatDate, v.EndDate, time.Local)
  167. if tmpErr != nil {
  168. errMsg = "规则配置的截止日期异常,请重新填写"
  169. return
  170. }
  171. // 没有数据,自己瞎测试
  172. //switch v.RuleType {
  173. //case 3: //3:同比
  174. // v.Value = "0.1"
  175. //case 4: //4:同差
  176. // v.Value = "10"
  177. //case 5: //5:环比
  178. // v.Value = "0.1"
  179. //case 6: //6:环差
  180. // v.Value = "0.1"
  181. //case 7: //7:N期移动均值
  182. // v.Value = "5"
  183. //case 8: //8:N期段线性外推值
  184. // v.Value = "5"
  185. //}
  186. switch v.RuleType {
  187. case 8: //N期段线性外推值
  188. valInt, tmpErr := strconv.Atoi(v.Value)
  189. if tmpErr != nil {
  190. errMsg = "N期段线性外推值的N值异常"
  191. return
  192. }
  193. if valInt <= 1 {
  194. errMsg = "N期段线性外推值的N值必须大于1"
  195. return
  196. }
  197. case 9: //9:动态环差
  198. for _, v := range v.EdbInfoIdArr {
  199. fromEdbMap[v.EdbInfoId] = v.EdbInfoId
  200. }
  201. }
  202. tmpPredictEdbConf := &data_manage.PredictEdbConf{
  203. PredictEdbInfoId: 0,
  204. SourceEdbInfoId: sourceEdbInfoId,
  205. RuleType: v.RuleType,
  206. //FixedValue: v.Value,
  207. Value: v.Value,
  208. EndDate: ruleEndDate,
  209. ModifyTime: time.Now(),
  210. CreateTime: time.Now(),
  211. }
  212. edbInfo.EndDate = v.EndDate
  213. predictEdbConfList = append(predictEdbConfList, tmpPredictEdbConf)
  214. }
  215. err = data_manage.AddPredictEdb(edbInfo, calculateMappingItem, predictEdbConfList)
  216. if err != nil {
  217. errMsg = "保存失败"
  218. err = errors.New("保存失败,Err:" + err.Error())
  219. return
  220. }
  221. //新增操作日志
  222. {
  223. edbLog := new(data_manage.EdbInfoLog)
  224. edbLog.EdbInfoId = edbInfo.EdbInfoId
  225. edbLog.SourceName = edbInfo.SourceName
  226. edbLog.Source = edbInfo.Source
  227. edbLog.EdbCode = edbInfo.EdbCode
  228. edbLog.EdbName = edbInfo.EdbName
  229. edbLog.ClassifyId = edbInfo.ClassifyId
  230. edbLog.SysUserId = sysUserId
  231. edbLog.SysUserRealName = sysUserName
  232. edbLog.CreateTime = time.Now()
  233. edbLog.Content = requestBody
  234. edbLog.Status = "新增指标"
  235. edbLog.Method = requestUrl
  236. go data_manage.AddEdbInfoLog(edbLog)
  237. }
  238. //添加es
  239. AddOrEditEdbInfoToEs(edbInfo.EdbInfoId)
  240. return
  241. }
  242. // EditPredictEdbInfo 编辑预测指标
  243. func EditPredictEdbInfo(edbInfoId, classifyId int, edbName string, ruleList []request.RuleConfig, sysUserId int, sysUserName, requestBody, requestUrl string) (edbInfo *data_manage.EdbInfo, err error, errMsg string) {
  244. // 指标信息校验
  245. {
  246. edbInfo, err = data_manage.GetEdbInfoById(edbInfoId)
  247. if err != nil && err.Error() != utils.ErrNoRow() {
  248. errMsg = "修改失败"
  249. err = errors.New("获取预测指标失败,Err:" + err.Error())
  250. return
  251. }
  252. if edbInfo == nil {
  253. errMsg = "找不到该预测指标"
  254. err = nil
  255. return
  256. }
  257. //必须是普通的指标
  258. if edbInfo.EdbInfoType != 1 {
  259. errMsg = "指标异常,不是预测指标"
  260. return
  261. }
  262. }
  263. var predictEdbConf *data_manage.PredictEdbConf
  264. // 指标配置信息校验
  265. {
  266. // 查找该预测指标配置
  267. predictEdbConfList, tmpErr := data_manage.GetPredictEdbConfListById(edbInfo.EdbInfoId)
  268. if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
  269. errMsg = "修改失败"
  270. err = errors.New("获取预测指标配置信息失败,Err:" + tmpErr.Error())
  271. return
  272. }
  273. if len(predictEdbConfList) == 0 {
  274. errMsg = "找不到该预测指标配置"
  275. err = nil
  276. return
  277. }
  278. predictEdbConf = predictEdbConfList[0]
  279. }
  280. //判断指标名称是否存在
  281. var condition string
  282. var pars []interface{}
  283. condition += " AND edb_info_id<>? "
  284. pars = append(pars, edbInfoId)
  285. condition += " AND edb_info_type=? "
  286. pars = append(pars, 1)
  287. condition += " AND edb_name=? "
  288. pars = append(pars, edbName)
  289. count, err := data_manage.GetEdbInfoCountByCondition(condition, pars)
  290. if err != nil {
  291. errMsg = "判断指标名称是否存在失败"
  292. err = errors.New("判断指标名称是否存在失败,Err:" + err.Error())
  293. return
  294. }
  295. if count > 0 {
  296. errMsg = "指标名称已存在,请重新填写"
  297. return
  298. }
  299. edbInfo.EdbName = edbName
  300. edbInfo.EdbNameSource = edbName
  301. edbInfo.ClassifyId = classifyId
  302. edbInfo.ModifyTime = time.Now()
  303. updateEdbInfoCol := []string{"EdbName", "EdbNameSource", "ClassifyId", "EndDate", "ModifyTime"}
  304. // 预测指标配置
  305. predictEdbConfList := make([]*data_manage.PredictEdbConf, 0)
  306. for _, v := range ruleList {
  307. // 预测指标配置
  308. ruleEndDate, tmpErr := time.ParseInLocation(utils.FormatDate, v.EndDate, time.Local)
  309. if tmpErr != nil {
  310. errMsg = "规则配置的截止日期异常,请重新填写"
  311. return
  312. }
  313. switch v.RuleType {
  314. case 8: //N期段线性外推值
  315. valInt, tmpErr := strconv.Atoi(v.Value)
  316. if tmpErr != nil {
  317. errMsg = "N期段线性外推值的N值异常"
  318. return
  319. }
  320. if valInt <= 1 {
  321. errMsg = "N期段线性外推值的N值必须大于1"
  322. return
  323. }
  324. case 9: //9:动态环差
  325. }
  326. tmpPredictEdbConf := &data_manage.PredictEdbConf{
  327. PredictEdbInfoId: edbInfoId,
  328. SourceEdbInfoId: predictEdbConf.SourceEdbInfoId,
  329. RuleType: v.RuleType,
  330. //FixedValue: v.Value,
  331. Value: v.Value,
  332. EndDate: ruleEndDate,
  333. ModifyTime: time.Now(),
  334. CreateTime: time.Now(),
  335. }
  336. predictEdbConfList = append(predictEdbConfList, tmpPredictEdbConf)
  337. edbInfo.EndDate = v.EndDate
  338. }
  339. err = data_manage.EditPredictEdb(edbInfo, predictEdbConfList, updateEdbInfoCol)
  340. if err != nil {
  341. errMsg = "保存失败"
  342. err = errors.New("保存失败,Err:" + err.Error())
  343. return
  344. }
  345. //新增操作日志
  346. {
  347. edbLog := new(data_manage.EdbInfoLog)
  348. edbLog.EdbInfoId = edbInfo.EdbInfoId
  349. edbLog.SourceName = edbInfo.SourceName
  350. edbLog.Source = edbInfo.Source
  351. edbLog.EdbCode = edbInfo.EdbCode
  352. edbLog.EdbName = edbInfo.EdbName
  353. edbLog.ClassifyId = edbInfo.ClassifyId
  354. edbLog.SysUserId = sysUserId
  355. edbLog.SysUserRealName = sysUserName
  356. edbLog.CreateTime = time.Now()
  357. edbLog.Content = requestBody
  358. edbLog.Status = "编辑指标"
  359. edbLog.Method = requestUrl
  360. go data_manage.AddEdbInfoLog(edbLog)
  361. }
  362. //添加es
  363. AddOrEditEdbInfoToEs(edbInfoId)
  364. // 刷新关联指标
  365. go EdbInfoRefreshAllFromBaseV2(edbInfo.EdbInfoId, true)
  366. return
  367. }
  368. // RefreshPredictEdbInfo 刷新预测指标
  369. func RefreshPredictEdbInfo(edbInfoId int, refreshAll bool) (edbInfo *data_manage.EdbInfo, err error, errMsg string) {
  370. // 指标信息校验
  371. {
  372. edbInfo, err = data_manage.GetEdbInfoById(edbInfoId)
  373. if err != nil && err.Error() != utils.ErrNoRow() {
  374. errMsg = "刷新失败"
  375. err = errors.New("获取预测指标失败,Err:" + err.Error())
  376. return
  377. }
  378. if edbInfo == nil {
  379. errMsg = "找不到该预测指标"
  380. err = nil
  381. return
  382. }
  383. //必须是预测的指标
  384. if edbInfo.EdbInfoType != 1 {
  385. errMsg = "指标异常,不是预测指标"
  386. return
  387. }
  388. }
  389. err = EdbInfoRefreshAllFromBaseV2(edbInfo.EdbInfoId, refreshAll)
  390. return
  391. }
  392. // MovePredictEdbInfo 移动预测指标
  393. func MovePredictEdbInfo(edbInfoId, classifyId, prevEdbInfoId, nextEdbInfoId int, sysUser *system.Admin, requestBody, requestUrl string) (err error, errMsg string) {
  394. //判断分类是否存在
  395. count, _ := data_manage.GetEdbClassifyCountById(classifyId)
  396. if count <= 0 {
  397. errMsg = "分类已被删除,不可移动,请刷新页面"
  398. return
  399. }
  400. edbInfo, err := data_manage.GetEdbInfoById(edbInfoId)
  401. if err != nil {
  402. if err != nil && err.Error() != utils.ErrNoRow() {
  403. errMsg = "移动失败"
  404. err = errors.New("获取预测指标失败,Err:" + err.Error())
  405. return
  406. }
  407. if edbInfo == nil {
  408. errMsg = "找不到该预测指标"
  409. err = nil
  410. return
  411. }
  412. return
  413. }
  414. // 移动权限校验
  415. button := GetEdbOpButton(sysUser, edbInfo.SysUserId, edbInfo.EdbType, edbInfo.EdbInfoType)
  416. if !button.MoveButton {
  417. errMsg = "无权限操作"
  418. err = nil
  419. return
  420. return
  421. }
  422. //如果改变了分类,那么移动该指标数据
  423. if edbInfo.ClassifyId != classifyId {
  424. err = data_manage.MoveEdbInfo(edbInfoId, classifyId)
  425. if err != nil {
  426. errMsg = "移动失败"
  427. err = errors.New("移动预测指标失败,Err:" + err.Error())
  428. return
  429. }
  430. }
  431. updateCol := make([]string, 0)
  432. //如果有传入 上一个兄弟节点分类id
  433. if prevEdbInfoId > 0 {
  434. prevEdbInfo, tmpErr := data_manage.GetEdbInfoById(prevEdbInfoId)
  435. if tmpErr != nil {
  436. errMsg = "移动失败"
  437. err = errors.New("获取上一个兄弟节点分类信息失败,Err:" + tmpErr.Error())
  438. return
  439. }
  440. //如果是移动在两个兄弟节点之间
  441. if nextEdbInfoId > 0 {
  442. //下一个兄弟节点
  443. nextEdbInfo, tmpErr := data_manage.GetEdbInfoById(nextEdbInfoId)
  444. if tmpErr != nil {
  445. errMsg = "移动失败"
  446. err = errors.New("获取下一个兄弟节点分类信息失败,Err:" + tmpErr.Error())
  447. return
  448. }
  449. //如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
  450. if prevEdbInfo.Sort == nextEdbInfo.Sort || prevEdbInfo.Sort == edbInfo.Sort {
  451. //变更兄弟节点的排序
  452. updateSortStr := `sort + 2`
  453. _ = data_manage.UpdateEdbInfoSortByClassifyId(prevEdbInfo.ClassifyId, prevEdbInfo.Sort, prevEdbInfo.EdbInfoId, updateSortStr)
  454. } else {
  455. //如果下一个兄弟的排序权重正好是上个兄弟节点 的下一层,那么需要再加一层了
  456. if nextEdbInfo.Sort-prevEdbInfo.Sort == 1 {
  457. //变更兄弟节点的排序
  458. updateSortStr := `sort + 1`
  459. _ = data_manage.UpdateEdbInfoSortByClassifyId(prevEdbInfo.ClassifyId, prevEdbInfo.Sort, prevEdbInfo.EdbInfoId, updateSortStr)
  460. }
  461. }
  462. }
  463. edbInfo.Sort = prevEdbInfo.Sort + 1
  464. edbInfo.ModifyTime = time.Now()
  465. updateCol = append(updateCol, "Sort", "ModifyTime")
  466. } else {
  467. firstClassify, tmpErr := data_manage.GetFirstEdbInfoByClassifyId(classifyId)
  468. if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
  469. errMsg = "移动失败"
  470. err = errors.New("获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + err.Error())
  471. return
  472. }
  473. //如果该分类下存在其他分类,且第一个其他分类的排序等于0,那么需要调整排序
  474. if firstClassify != nil && firstClassify.Sort == 0 {
  475. updateSortStr := ` sort + 1 `
  476. _ = data_manage.UpdateEdbInfoSortByClassifyId(firstClassify.ClassifyId, 0, firstClassify.EdbInfoId-1, updateSortStr)
  477. }
  478. edbInfo.Sort = 0 //那就是排在第一位
  479. edbInfo.ModifyTime = time.Now()
  480. updateCol = append(updateCol, "Sort", "ModifyTime")
  481. }
  482. //更新
  483. if len(updateCol) > 0 {
  484. err = edbInfo.Update(updateCol)
  485. }
  486. if err != nil {
  487. errMsg = "移动失败"
  488. err = errors.New("修改失败,Err:" + err.Error())
  489. return
  490. }
  491. //新增操作日志
  492. {
  493. edbLog := new(data_manage.EdbInfoLog)
  494. edbLog.EdbInfoId = edbInfo.EdbInfoId
  495. edbLog.SourceName = edbInfo.SourceName
  496. edbLog.Source = edbInfo.Source
  497. edbLog.EdbCode = edbInfo.EdbCode
  498. edbLog.EdbName = edbInfo.EdbName
  499. edbLog.ClassifyId = edbInfo.ClassifyId
  500. edbLog.SysUserId = sysUser.AdminId
  501. edbLog.SysUserRealName = sysUser.RealName
  502. edbLog.CreateTime = time.Now()
  503. edbLog.Content = requestBody
  504. edbLog.Status = "移动指标"
  505. edbLog.Method = requestUrl
  506. go data_manage.AddEdbInfoLog(edbLog)
  507. }
  508. return
  509. }
  510. // GetPredictEdbInfoDataList 获取预测指标的未来数据
  511. func GetPredictEdbInfoDataList(predictEdbConf data_manage.PredictEdbConf, latestDateStr string, lastDataValue float64, endDateStr, frequency string) (predictEdbInfoData []*data_manage.EdbData, err error) {
  512. endDate, err := time.ParseInLocation(utils.FormatDate, endDateStr, time.Local)
  513. if err != nil {
  514. return
  515. }
  516. latestDate, err := time.ParseInLocation(utils.FormatDate, latestDateStr, time.Local)
  517. if err != nil {
  518. return
  519. }
  520. dataValue := lastDataValue
  521. if predictEdbConf.RuleType == 2 {
  522. dataValue = predictEdbConf.FixedValue
  523. }
  524. //获取后面的预测数据
  525. dayList := getPredictEdbDayList(latestDate, endDate, frequency)
  526. predictEdbInfoData = make([]*data_manage.EdbData, 0)
  527. lenDayList := len(dayList)
  528. if lenDayList > 0 {
  529. for i := lenDayList - 1; i >= 0; i-- {
  530. v := dayList[i]
  531. predictEdbInfoData = append(predictEdbInfoData, &data_manage.EdbData{
  532. EdbDataId: predictEdbConf.PredictEdbInfoId + 100000 + i,
  533. EdbInfoId: predictEdbConf.PredictEdbInfoId,
  534. DataTime: v.Format(utils.FormatDate),
  535. Value: dataValue,
  536. })
  537. }
  538. }
  539. return
  540. }
  541. // GetChartPredictEdbInfoDataList 获取图表的预测指标的未来数据
  542. func GetChartPredictEdbInfoDataList(predictEdbConf data_manage.PredictEdbConf, filtrateStartDateStr, latestDateStr string, lastDataValue float64, endDateStr, frequency string) (predictEdbInfoData []*data_manage.EdbDataList, err error) {
  543. endDate, err := time.ParseInLocation(utils.FormatDate, endDateStr, time.Local)
  544. if err != nil {
  545. return
  546. }
  547. latestDate, err := time.ParseInLocation(utils.FormatDate, latestDateStr, time.Local)
  548. if err != nil {
  549. return
  550. }
  551. // 开始预测数据的时间
  552. startDate := latestDate
  553. // 如果有筛选时间的话
  554. if filtrateStartDateStr != `` {
  555. filtrateStartDate, tmpErr := time.ParseInLocation(utils.FormatDate, filtrateStartDateStr, time.Local)
  556. if tmpErr != nil {
  557. err = tmpErr
  558. return
  559. }
  560. //如果筛选时间晚于实际数据时间,那么就以筛选时间作为获取预测数据的时间
  561. if filtrateStartDate.After(latestDate) {
  562. startDate = filtrateStartDate.AddDate(0, 0, -1)
  563. }
  564. }
  565. dataValue := lastDataValue
  566. if predictEdbConf.RuleType == 2 {
  567. dataValue = predictEdbConf.FixedValue
  568. }
  569. //获取后面的预测数据
  570. dayList := getPredictEdbDayList(startDate, endDate, frequency)
  571. predictEdbInfoData = make([]*data_manage.EdbDataList, 0)
  572. for k, v := range dayList {
  573. predictEdbInfoData = append(predictEdbInfoData, &data_manage.EdbDataList{
  574. EdbDataId: predictEdbConf.PredictEdbInfoId + 100000 + k,
  575. EdbInfoId: predictEdbConf.PredictEdbInfoId,
  576. DataTime: v.Format(utils.FormatDate),
  577. Value: dataValue,
  578. DataTimestamp: v.UnixNano() / 1e6,
  579. })
  580. }
  581. return
  582. }
  583. // GetChartPredictEdbInfoDataListByConfList 获取图表的预测指标的未来数据
  584. func GetChartPredictEdbInfoDataListByConfList(predictEdbConfList []data_manage.PredictEdbConfAndData, filtrateStartDateStr, latestDateStr, endDateStr, frequency string, realPredictEdbInfoData []*data_manage.EdbDataList) (predictEdbInfoData []*data_manage.EdbDataList, minValue, maxValue float64, err error, errMsg string) {
  585. endDate, err := time.ParseInLocation(utils.FormatDate, endDateStr, time.Local)
  586. if err != nil {
  587. return
  588. }
  589. latestDate, err := time.ParseInLocation(utils.FormatDate, latestDateStr, time.Local)
  590. if err != nil {
  591. return
  592. }
  593. // 开始预测数据的时间
  594. startDate := latestDate
  595. // 如果有筛选时间的话
  596. if filtrateStartDateStr != `` {
  597. filtrateStartDate, tmpErr := time.ParseInLocation(utils.FormatDate, filtrateStartDateStr, time.Local)
  598. if tmpErr != nil {
  599. err = tmpErr
  600. return
  601. }
  602. //如果筛选时间晚于实际数据时间,那么就以筛选时间作为获取预测数据的时间
  603. if filtrateStartDate.After(latestDate) {
  604. startDate = filtrateStartDate.AddDate(0, 0, -1)
  605. }
  606. }
  607. //var dateArr []string
  608. // 对应日期的值
  609. existMap := make(map[string]float64)
  610. for _, v := range realPredictEdbInfoData {
  611. //dateArr = append(dateArr, v.DataTime)
  612. existMap[v.DataTime] = v.Value
  613. }
  614. predictEdbInfoData = make([]*data_manage.EdbDataList, 0)
  615. //dataValue := lastDataValue
  616. //预测规则,1:最新,2:固定值,3:同比,4:同差,5:环比,6:环差,7:N期移动均值,8:N期段线性外推值
  617. for _, predictEdbConf := range predictEdbConfList {
  618. dataEndTime := endDate
  619. if predictEdbConf.EndDate.Before(dataEndTime) {
  620. dataEndTime = predictEdbConf.EndDate
  621. }
  622. var tmpMinValue, tmpMaxValue float64 // 当前预测结果中的最大/最小值
  623. dayList := getPredictEdbDayList(startDate, dataEndTime, frequency)
  624. if len(dayList) <= 0 { // 如果未来没有日期的话,那么就退出当前循环,进入下一个循环
  625. continue
  626. }
  627. switch predictEdbConf.RuleType {
  628. case 1: //1:最新
  629. var lastDataValue float64 //最新值
  630. tmpAllData := make([]*data_manage.EdbDataList, 0)
  631. tmpAllData = append(tmpAllData, realPredictEdbInfoData...)
  632. tmpAllData = append(tmpAllData, predictEdbInfoData...)
  633. lenTmpAllData := len(tmpAllData)
  634. if lenTmpAllData > 0 {
  635. lastDataValue = tmpAllData[lenTmpAllData-1].Value
  636. }
  637. predictEdbInfoData = GetChartPredictEdbInfoDataListByRule1(predictEdbConf.PredictEdbInfoId, lastDataValue, dayList, predictEdbInfoData, existMap)
  638. tmpMaxValue = lastDataValue
  639. tmpMinValue = lastDataValue
  640. case 2: //2:固定值
  641. tmpValDecimal, tmpErr := decimal.NewFromString(predictEdbConf.Value)
  642. if tmpErr != nil {
  643. err = tmpErr
  644. return
  645. }
  646. dataValue, _ := tmpValDecimal.Float64()
  647. predictEdbInfoData = GetChartPredictEdbInfoDataListByRule1(predictEdbConf.PredictEdbInfoId, dataValue, dayList, predictEdbInfoData, existMap)
  648. tmpMaxValue = dataValue
  649. tmpMinValue = dataValue
  650. case 3: //3:同比
  651. tmpValDecimal, tmpErr := decimal.NewFromString(predictEdbConf.Value)
  652. if tmpErr != nil {
  653. err = tmpErr
  654. return
  655. }
  656. tbValue, _ := tmpValDecimal.Float64()
  657. predictEdbInfoData, tmpMinValue, tmpMaxValue = GetChartPredictEdbInfoDataListByRuleTb(predictEdbConf.PredictEdbInfoId, tbValue, dayList, frequency, realPredictEdbInfoData, predictEdbInfoData, existMap)
  658. case 4: //4:同差
  659. tmpValDecimal, tmpErr := decimal.NewFromString(predictEdbConf.Value)
  660. if tmpErr != nil {
  661. err = tmpErr
  662. return
  663. }
  664. tcValue, _ := tmpValDecimal.Float64()
  665. predictEdbInfoData, tmpMinValue, tmpMaxValue = GetChartPredictEdbInfoDataListByRuleTc(predictEdbConf.PredictEdbInfoId, tcValue, dayList, frequency, realPredictEdbInfoData, predictEdbInfoData, existMap)
  666. case 5: //5:环比
  667. tmpValDecimal, tmpErr := decimal.NewFromString(predictEdbConf.Value)
  668. if tmpErr != nil {
  669. err = tmpErr
  670. return
  671. }
  672. hbValue, _ := tmpValDecimal.Float64()
  673. predictEdbInfoData, tmpMinValue, tmpMaxValue = GetChartPredictEdbInfoDataListByRuleHb(predictEdbConf.PredictEdbInfoId, hbValue, dayList, realPredictEdbInfoData, predictEdbInfoData, existMap)
  674. case 6: //6:环差
  675. tmpValDecimal, tmpErr := decimal.NewFromString(predictEdbConf.Value)
  676. if tmpErr != nil {
  677. err = tmpErr
  678. return
  679. }
  680. hcValue, _ := tmpValDecimal.Float64()
  681. predictEdbInfoData, tmpMinValue, tmpMaxValue = GetChartPredictEdbInfoDataListByRuleHc(predictEdbConf.PredictEdbInfoId, hcValue, dayList, realPredictEdbInfoData, predictEdbInfoData, existMap)
  682. case 7: //7:N期移动均值
  683. nValue, tmpErr := strconv.Atoi(predictEdbConf.Value)
  684. if tmpErr != nil {
  685. err = tmpErr
  686. return
  687. }
  688. predictEdbInfoData, tmpMinValue, tmpMaxValue = GetChartPredictEdbInfoDataListByRuleNMoveMeanValue(predictEdbConf.PredictEdbInfoId, nValue, dayList, realPredictEdbInfoData, predictEdbInfoData, existMap)
  689. case 8: //8:N期段线性外推值
  690. nValue, tmpErr := strconv.Atoi(predictEdbConf.Value)
  691. if tmpErr != nil {
  692. err = tmpErr
  693. return
  694. }
  695. if nValue <= 1 {
  696. errMsg = `N期段线性外推值的N值必须大于1`
  697. err = errors.New(errMsg)
  698. return
  699. }
  700. predictEdbInfoData, tmpMinValue, tmpMaxValue, err = GetChartPredictEdbInfoDataListByRuleNLinearRegression(predictEdbConf.PredictEdbInfoId, nValue, dayList, realPredictEdbInfoData, predictEdbInfoData, existMap)
  701. if err != nil {
  702. return
  703. }
  704. case 9: //9:动态环差”预测规则;
  705. //规则计算的环差值map
  706. hcDataMap := make(map[string]float64)
  707. if predictEdbConf.PredictEdbInfoId > 0 { //已经生成的动态数据
  708. tmpPredictEdbRuleDataList, tmpErr := data_manage.GetPredictEdbRuleDataList(predictEdbConf.PredictEdbInfoId, predictEdbConf.ConfigId, startDate.Format(utils.FormatDate), endDate.Format(utils.FormatDate))
  709. if tmpErr != nil {
  710. err = tmpErr
  711. return
  712. }
  713. for _, v := range tmpPredictEdbRuleDataList {
  714. hcDataMap[v.DataTime] = v.Value
  715. }
  716. } else { //未生成的动态数据,需要使用外部传入的数据进行计算
  717. if len(predictEdbConf.DataList) <= 0 {
  718. return
  719. }
  720. for _, v := range predictEdbConf.DataList {
  721. currentDate, tmpErr := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
  722. if tmpErr != nil {
  723. continue
  724. }
  725. // 只处理时间段内的数据
  726. if currentDate.Before(startDate) || currentDate.After(endDate) {
  727. continue
  728. }
  729. hcDataMap[v.DataTime] = v.Value
  730. }
  731. }
  732. predictEdbInfoData, tmpMinValue, tmpMaxValue = GetChartPredictEdbInfoDataListByRuleTrendsHC(predictEdbConf.PredictEdbInfoId, dayList, realPredictEdbInfoData, predictEdbInfoData, hcDataMap, existMap)
  733. case 10: //10:根据 给定终值后插值 规则获取预测数据
  734. tmpValDecimal, tmpErr := decimal.NewFromString(predictEdbConf.Value)
  735. if tmpErr != nil {
  736. err = tmpErr
  737. return
  738. }
  739. finalValue, _ := tmpValDecimal.Float64()
  740. predictEdbInfoData, tmpMinValue, tmpMaxValue = GetChartPredictEdbInfoDataListByRuleFinalValueHc(predictEdbConf.PredictEdbInfoId, finalValue, dayList, realPredictEdbInfoData, predictEdbInfoData, existMap)
  741. case 11: //11:根据 季节性 规则获取预测数据
  742. predictEdbInfoData, tmpMinValue, tmpMaxValue, err = GetChartPredictEdbInfoDataListByRuleSeason(predictEdbConf.PredictEdbInfoId, predictEdbConf.Value, dayList, realPredictEdbInfoData, predictEdbInfoData, existMap)
  743. if err != nil {
  744. return
  745. }
  746. case 12: //12:根据 移动平均同比 规则获取预测数据
  747. var moveAverageConf MoveAverageConf
  748. tmpErr := json.Unmarshal([]byte(predictEdbConf.Value), &moveAverageConf)
  749. if tmpErr != nil {
  750. err = errors.New("季节性配置信息异常:" + tmpErr.Error())
  751. return
  752. }
  753. predictEdbInfoData, tmpMinValue, tmpMaxValue, err = GetChartPredictEdbInfoDataListByRuleMoveAverageTb(predictEdbConf.PredictEdbInfoId, moveAverageConf.NValue, moveAverageConf.Year, dayList, realPredictEdbInfoData, predictEdbInfoData, existMap)
  754. if err != nil {
  755. return
  756. }
  757. case 13: //13:根据 同比增速差值 规则获取预测数据
  758. tmpValDecimal, tmpErr := decimal.NewFromString(predictEdbConf.Value)
  759. if tmpErr != nil {
  760. err = tmpErr
  761. return
  762. }
  763. tbEndValue, _ := tmpValDecimal.Float64()
  764. predictEdbInfoData, tmpMinValue, tmpMaxValue = GetChartPredictEdbInfoDataListByRuleTbzscz(predictEdbConf.PredictEdbInfoId, tbEndValue, dayList, frequency, realPredictEdbInfoData, predictEdbInfoData, existMap)
  765. case 14: //14:根据 一元线性拟合 规则获取预测数据
  766. var ruleConf RuleLineNhConf
  767. err = json.Unmarshal([]byte(predictEdbConf.Value), &ruleConf)
  768. if err != nil {
  769. err = errors.New("一元线性拟合配置信息异常:" + err.Error())
  770. return
  771. }
  772. // 规则计算的拟合残差值map
  773. newNhccDataMap := make(map[string]float64)
  774. if predictEdbConf.PredictEdbInfoId > 0 { //已经生成的动态数据
  775. tmpPredictEdbRuleDataList, tmpErr := data_manage.GetPredictEdbRuleDataList(predictEdbConf.PredictEdbInfoId, predictEdbConf.ConfigId, "", "")
  776. if tmpErr != nil {
  777. err = tmpErr
  778. return
  779. }
  780. for _, v := range tmpPredictEdbRuleDataList {
  781. newNhccDataMap[v.DataTime] = v.Value
  782. }
  783. } else { //未生成的动态数据,需要使用外部传入的数据进行计算
  784. newNhccDataMap, err = getCalculateNhccData(append(realPredictEdbInfoData, predictEdbInfoData...), ruleConf)
  785. if err != nil {
  786. return
  787. }
  788. }
  789. predictEdbInfoData, tmpMinValue, tmpMaxValue, err = GetChartPredictEdbInfoDataListByRuleLineNh(predictEdbConf.PredictEdbInfoId, dayList, realPredictEdbInfoData, predictEdbInfoData, newNhccDataMap, existMap)
  790. if err != nil {
  791. return
  792. }
  793. case 15: //15:N年均值:过去N年同期均值。过去N年可以连续或者不连续,指标数据均用线性插值补全为日度数据后计算;
  794. predictEdbInfoData, tmpMinValue, tmpMaxValue, err = GetChartPredictEdbInfoDataListByRuleNAnnualAverage(predictEdbConf.PredictEdbInfoId, predictEdbConf.Value, dayList, realPredictEdbInfoData, predictEdbInfoData, existMap)
  795. if err != nil {
  796. return
  797. }
  798. case 16: //16:年度值倒推
  799. predictEdbInfoData, tmpMinValue, tmpMaxValue, err = GetChartPredictEdbInfoDataListByRuleAnnualValueInversion(predictEdbConf.PredictEdbInfoId, predictEdbConf.Value, dayList, frequency, realPredictEdbInfoData, predictEdbInfoData, existMap)
  800. if err != nil {
  801. return
  802. }
  803. }
  804. // 下一个规则的开始日期
  805. {
  806. lenPredictEdbInfoData := len(predictEdbInfoData)
  807. if lenPredictEdbInfoData > 0 {
  808. tmpDataEndTime, _ := time.ParseInLocation(utils.FormatDate, predictEdbInfoData[lenPredictEdbInfoData-1].DataTime, time.Local)
  809. if startDate.Before(tmpDataEndTime) {
  810. startDate = tmpDataEndTime
  811. }
  812. }
  813. }
  814. if tmpMinValue < minValue {
  815. minValue = tmpMinValue
  816. }
  817. if tmpMaxValue > maxValue {
  818. maxValue = tmpMaxValue
  819. }
  820. }
  821. return
  822. }
  823. // GetPredictEdbDayList 获取预测指标日期列表
  824. func getPredictEdbDayList(startDate, endDate time.Time, frequency string) (dayList []time.Time) {
  825. //if !utils.InArrayByStr([]string{"日度", "周度", "月度"}, frequency)
  826. switch frequency {
  827. case "日度":
  828. for currDate := startDate.AddDate(0, 0, 1); currDate.Before(endDate) || currDate.Equal(endDate); currDate = currDate.AddDate(0, 0, 1) {
  829. //周六、日排除
  830. if currDate.Weekday() == time.Sunday || currDate.Weekday() == time.Saturday {
  831. continue
  832. }
  833. dayList = append(dayList, currDate)
  834. }
  835. case "周度":
  836. //nextDate := startDate.AddDate(0, 0, 7)
  837. for currDate := startDate.AddDate(0, 0, 7); currDate.Before(endDate) || currDate.Equal(endDate); currDate = currDate.AddDate(0, 0, 7) {
  838. dayList = append(dayList, currDate)
  839. }
  840. case "旬度":
  841. for currDate := startDate.AddDate(0, 0, 1); currDate.Before(endDate) || currDate.Equal(endDate); {
  842. nextDate := currDate.AddDate(0, 0, 1)
  843. //每个月的10号、20号、最后一天,那么就写入
  844. if nextDate.Day() == 11 || nextDate.Day() == 21 || nextDate.Day() == 1 {
  845. dayList = append(dayList, currDate)
  846. }
  847. currDate = nextDate
  848. }
  849. case "月度":
  850. for currDate := startDate; currDate.Before(endDate) || currDate.Equal(endDate); {
  851. currDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, time.Now().Location()).AddDate(0, 1, -1)
  852. if !currDate.After(endDate) && !currDate.Equal(startDate) {
  853. dayList = append(dayList, currDate)
  854. }
  855. currDate = currDate.AddDate(0, 0, 1)
  856. }
  857. case "季度":
  858. for currDate := startDate; currDate.Before(endDate) || currDate.Equal(endDate); {
  859. // 每月的最后一天
  860. currDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, time.Now().Location()).AddDate(0, 1, -1)
  861. if !currDate.After(endDate) && !currDate.Equal(startDate) {
  862. // 季度日期就写入,否则不写入
  863. if currDate.Month() == 3 || currDate.Month() == 6 || currDate.Month() == 9 || currDate.Month() == 12 {
  864. dayList = append(dayList, currDate)
  865. }
  866. }
  867. currDate = currDate.AddDate(0, 0, 1)
  868. }
  869. case "半年度":
  870. for currDate := startDate; currDate.Before(endDate) || currDate.Equal(endDate); {
  871. // 每月的最后一天
  872. currDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, time.Now().Location()).AddDate(0, 1, -1)
  873. if !currDate.After(endDate) && !currDate.Equal(startDate) {
  874. // 半年度日期就写入,否则不写入
  875. if currDate.Month() == 6 || currDate.Month() == 12 {
  876. dayList = append(dayList, currDate)
  877. }
  878. }
  879. currDate = currDate.AddDate(0, 0, 1)
  880. }
  881. case "年度":
  882. for currDate := startDate; currDate.Before(endDate) || currDate.Equal(endDate); {
  883. currDate = time.Date(currDate.Year()+1, 12, 31, 0, 0, 0, 0, time.Now().Location())
  884. if !currDate.After(endDate) && !currDate.Equal(startDate) {
  885. dayList = append(dayList, currDate)
  886. }
  887. }
  888. }
  889. return
  890. }
  891. // GetPredictDataListByPredictEdbInfoId 根据预测指标id获取预测指标的数据
  892. func GetPredictDataListByPredictEdbInfoId(edbInfoId int, startDate, endDate string, isTimeBetween bool) (edbInfo *data_manage.EdbInfo, dataList []*data_manage.EdbDataList, sourceEdbInfoItem *data_manage.EdbInfo, predictEdbConf *data_manage.PredictEdbConf, err error, errMsg string) {
  893. edbInfo, err = data_manage.GetEdbInfoById(edbInfoId)
  894. if err != nil {
  895. errMsg = `获取预测指标信息失败`
  896. return
  897. }
  898. dataList, sourceEdbInfoItem, predictEdbConf, err, errMsg = GetPredictDataListByPredictEdbInfo(edbInfo, startDate, endDate, isTimeBetween)
  899. return
  900. }
  901. // GetPredictDataListByPredictEdbInfo 根据预测指标信息获取预测指标的数据
  902. func GetPredictDataListByPredictEdbInfo(edbInfo *data_manage.EdbInfo, startDate, endDate string, isTimeBetween bool) (dataList []*data_manage.EdbDataList, sourceEdbInfoItem *data_manage.EdbInfo, predictEdbConf *data_manage.PredictEdbConf, err error, errMsg string) {
  903. // 非计算指标,直接从表里获取数据
  904. if edbInfo.EdbType != 1 {
  905. if !isTimeBetween { //如果不是区间数据,那么就结束日期为空
  906. endDate = ``
  907. }
  908. return GetPredictCalculateDataListByPredictEdbInfo(edbInfo, startDate, endDate)
  909. }
  910. // 查找该预测指标配置
  911. predictEdbConfList, err := data_manage.GetPredictEdbConfListById(edbInfo.EdbInfoId)
  912. if err != nil && err.Error() != utils.ErrNoRow() {
  913. errMsg = "获取预测指标配置信息失败"
  914. return
  915. }
  916. if len(predictEdbConfList) == 0 {
  917. errMsg = "获取预测指标配置信息失败"
  918. err = errors.New(errMsg)
  919. return
  920. }
  921. predictEdbConf = predictEdbConfList[0]
  922. // 来源指标
  923. sourceEdbInfoItem, err = data_manage.GetEdbInfoById(predictEdbConf.SourceEdbInfoId)
  924. if err != nil {
  925. if err.Error() == utils.ErrNoRow() {
  926. errMsg = "找不到来源指标信息"
  927. err = errors.New(errMsg)
  928. }
  929. return
  930. }
  931. allDataList := make([]*data_manage.EdbDataList, 0)
  932. //获取指标数据(实际已生成)
  933. dataList, err = data_manage.GetEdbDataList(sourceEdbInfoItem.Source, sourceEdbInfoItem.EdbInfoId, startDate, endDate)
  934. if err != nil {
  935. return
  936. }
  937. // 如果选择了日期,那么需要筛选所有的数据,用于未来指标的生成
  938. if startDate != `` {
  939. allDataList, err = data_manage.GetEdbDataList(sourceEdbInfoItem.Source, sourceEdbInfoItem.EdbInfoId, "", "")
  940. if err != nil {
  941. return
  942. }
  943. } else {
  944. allDataList = dataList
  945. }
  946. // 获取预测指标未来的数据
  947. predictDataList := make([]*data_manage.EdbDataList, 0)
  948. endDateStr := edbInfo.EndDate //预测指标的结束日期
  949. if isTimeBetween { //如果是时间区间,那么
  950. reqEndDateTime, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
  951. endDateTime, _ := time.ParseInLocation(utils.FormatDate, edbInfo.EndDate, time.Local)
  952. // 如果选择的时间区间结束日期 晚于 当天,那么预测数据截止到当天
  953. if reqEndDateTime.Before(endDateTime) {
  954. endDateStr = endDate
  955. }
  956. }
  957. //predictDataList, err = GetChartPredictEdbInfoDataList(*predictEdbConf, startDate, sourceEdbInfoItem.LatestDate, sourceEdbInfoItem.LatestValue, endDateStr, edbInfo.Frequency)
  958. predictEdbConfDataList := make([]data_manage.PredictEdbConfAndData, 0)
  959. for _, v := range predictEdbConfList {
  960. predictEdbConfDataList = append(predictEdbConfDataList, data_manage.PredictEdbConfAndData{
  961. ConfigId: v.ConfigId,
  962. PredictEdbInfoId: v.PredictEdbInfoId,
  963. SourceEdbInfoId: v.SourceEdbInfoId,
  964. RuleType: v.RuleType,
  965. FixedValue: v.FixedValue,
  966. Value: v.Value,
  967. EndDate: v.EndDate,
  968. ModifyTime: v.ModifyTime,
  969. CreateTime: v.CreateTime,
  970. DataList: make([]*data_manage.EdbDataList, 0),
  971. })
  972. }
  973. //var predictMinValue, predictMaxValue float64
  974. predictDataList, _, _, err, _ = GetChartPredictEdbInfoDataListByConfList(predictEdbConfDataList, startDate, sourceEdbInfoItem.LatestDate, endDateStr, edbInfo.Frequency, allDataList)
  975. if err != nil {
  976. return
  977. }
  978. dataList = append(dataList, predictDataList...)
  979. //if len(predictDataList) > 0 {
  980. // // 如果最小值 大于 预测值,那么将预测值作为最小值数据返回
  981. // if edbInfo.MinValue > predictMinValue {
  982. // edbInfo.MinValue = predictMinValue
  983. // }
  984. //
  985. // // 如果最大值 小于 预测值,那么将预测值作为最大值数据返回
  986. // if edbInfo.MaxValue < predictMaxValue {
  987. // edbInfo.MaxValue = predictMaxValue
  988. // }
  989. //}
  990. return
  991. }
  992. // GetChartDataList 通过完整的预测数据 进行 季节性图、公历、农历处理
  993. func GetChartDataList(dataList []*data_manage.EdbDataList, chartType int, calendar, latestDateStr, startDate string) (resultDataList interface{}, err error) {
  994. startDateReal := startDate
  995. calendarPreYear := 0
  996. if calendar == "农历" {
  997. newStartDateReal, err := time.Parse(utils.FormatDate, startDateReal)
  998. if err != nil {
  999. fmt.Println("time.Parse:" + err.Error())
  1000. }
  1001. calendarPreYear = newStartDateReal.Year() - 1
  1002. newStartDateReal = newStartDateReal.AddDate(-1, 0, 0)
  1003. startDateReal = newStartDateReal.Format(utils.FormatDate)
  1004. }
  1005. // 曲线图
  1006. if chartType == 1 {
  1007. resultDataList = dataList
  1008. return
  1009. }
  1010. //实际数据的截止日期
  1011. latestDate, tmpErr := time.Parse(utils.FormatDate, latestDateStr)
  1012. if tmpErr != nil {
  1013. err = errors.New(fmt.Sprint("获取最后实际数据的日期失败,Err:" + tmpErr.Error() + ";LatestDate:" + latestDateStr))
  1014. return
  1015. }
  1016. latestDateYear := latestDate.Year() //实际数据截止年份
  1017. if calendar == "农历" {
  1018. if len(dataList) <= 0 {
  1019. resultDataList = data_manage.EdbDataResult{}
  1020. } else {
  1021. result, tmpErr := data_manage.AddCalculateQuarterV4(dataList)
  1022. if tmpErr != nil {
  1023. err = errors.New("获取农历数据失败,Err:" + tmpErr.Error())
  1024. return
  1025. }
  1026. // 处理季节图的截止日期
  1027. for k, edbDataItems := range result.List {
  1028. var cuttingDataTimestamp int64
  1029. // 切割的日期时间字符串
  1030. cuttingDataTimeStr := latestDate.AddDate(0, 0, edbDataItems.BetweenDay).Format(utils.FormatDate)
  1031. //如果等于最后的实际日期,那么遍历找到该日期对应的时间戳,并将其赋值为 切割时间戳
  1032. if edbDataItems.Year >= latestDateYear {
  1033. for _, tmpData := range edbDataItems.Items {
  1034. if tmpData.DataTime == cuttingDataTimeStr {
  1035. cuttingDataTimestamp = tmpData.DataTimestamp
  1036. break
  1037. }
  1038. }
  1039. }
  1040. edbDataItems.CuttingDataTimestamp = cuttingDataTimestamp
  1041. result.List[k] = edbDataItems
  1042. }
  1043. if result.List[0].Year != calendarPreYear {
  1044. itemList := make([]*data_manage.EdbDataList, 0)
  1045. items := new(data_manage.EdbDataItems)
  1046. //items.Year = calendarPreYear
  1047. items.Items = itemList
  1048. newResult := new(data_manage.EdbDataResult)
  1049. newResult.List = append(newResult.List, items)
  1050. newResult.List = append(newResult.List, result.List...)
  1051. resultDataList = newResult
  1052. } else {
  1053. resultDataList = result
  1054. }
  1055. }
  1056. } else {
  1057. currentYear := time.Now().Year()
  1058. quarterDataList := make([]*data_manage.QuarterData, 0)
  1059. quarterMap := make(map[int][]*data_manage.EdbDataList)
  1060. var quarterArr []int
  1061. for _, v := range dataList {
  1062. itemDate, tmpErr := time.Parse(utils.FormatDate, v.DataTime)
  1063. if tmpErr != nil {
  1064. err = errors.New("季度指标日期转换,Err:" + tmpErr.Error() + ";DataTime:" + v.DataTime)
  1065. return
  1066. }
  1067. year := itemDate.Year()
  1068. newItemDate := itemDate.AddDate(currentYear-year, 0, 0)
  1069. timestamp := newItemDate.UnixNano() / 1e6
  1070. v.DataTimestamp = timestamp
  1071. if findVal, ok := quarterMap[year]; !ok {
  1072. quarterArr = append(quarterArr, year)
  1073. findVal = append(findVal, v)
  1074. quarterMap[year] = findVal
  1075. } else {
  1076. findVal = append(findVal, v)
  1077. quarterMap[year] = findVal
  1078. }
  1079. }
  1080. for _, v := range quarterArr {
  1081. itemList := quarterMap[v]
  1082. quarterItem := new(data_manage.QuarterData)
  1083. quarterItem.Year = v
  1084. quarterItem.DataList = itemList
  1085. //如果等于最后的实际日期,那么将切割时间戳记录
  1086. if v == latestDateYear {
  1087. var cuttingDataTimestamp int64
  1088. for _, tmpData := range itemList {
  1089. if tmpData.DataTime == latestDateStr {
  1090. cuttingDataTimestamp = tmpData.DataTimestamp
  1091. break
  1092. }
  1093. }
  1094. quarterItem.CuttingDataTimestamp = cuttingDataTimestamp
  1095. } else if v > latestDateYear {
  1096. //如果大于最后的实际日期,那么第一个点就是切割的时间戳
  1097. if len(itemList) > 0 {
  1098. quarterItem.CuttingDataTimestamp = itemList[0].DataTimestamp - 100
  1099. }
  1100. }
  1101. quarterDataList = append(quarterDataList, quarterItem)
  1102. }
  1103. resultDataList = quarterDataList
  1104. }
  1105. return
  1106. }
  1107. // GetPredictCalculateDataListByPredictEdbInfo 根据预测运算指标信息获取预测指标的数据
  1108. func GetPredictCalculateDataListByPredictEdbInfo(edbInfo *data_manage.EdbInfo, startDate, endDate string) (dataList []*data_manage.EdbDataList, sourceEdbInfoItem *data_manage.EdbInfo, predictEdbConf *data_manage.PredictEdbConf, err error, errMsg string) {
  1109. dataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.EdbInfoId, startDate, endDate)
  1110. return
  1111. }
  1112. // GetCalculateByRuleByNineParams 获取预测规则9的计算参数
  1113. func GetCalculateByRuleByNineParams(req request.RuleConfig) (formula string, edbInfoList []*data_manage.EdbInfo, edbInfoIdBytes []string, err error, errMsg string) {
  1114. formula = req.Value
  1115. formula = strings.Replace(formula, "(", "(", -1)
  1116. formula = strings.Replace(formula, ")", ")", -1)
  1117. formula = strings.Replace(formula, ",", ",", -1)
  1118. formula = strings.Replace(formula, "。", ".", -1)
  1119. formula = strings.Replace(formula, "%", "*0.01", -1)
  1120. //检验公式
  1121. var checkFormulaStr string
  1122. for _, tmpEdbInfoId := range req.EdbInfoIdArr {
  1123. checkFormulaStr += tmpEdbInfoId.FromTag + ","
  1124. edbInfoIdBytes = append(edbInfoIdBytes, tmpEdbInfoId.FromTag)
  1125. }
  1126. formulaMap := CheckFormula(formula)
  1127. for _, tmpFormula := range formulaMap {
  1128. if !strings.Contains(checkFormulaStr, tmpFormula) {
  1129. errMsg = "公式错误,请重新填写"
  1130. return
  1131. }
  1132. }
  1133. //关联的指标信息
  1134. edbInfoList = make([]*data_manage.EdbInfo, 0)
  1135. for _, tmpEdbInfoId := range req.EdbInfoIdArr {
  1136. fromEdbInfo, tmpErr := data_manage.GetEdbInfoById(tmpEdbInfoId.EdbInfoId)
  1137. if tmpErr != nil {
  1138. if tmpErr.Error() == utils.ErrNoRow() {
  1139. err = errors.New("指标 " + strconv.Itoa(tmpEdbInfoId.EdbInfoId) + " 不存在")
  1140. } else {
  1141. err = errors.New("获取指标失败:Err:" + tmpErr.Error())
  1142. }
  1143. errMsg = "数据计算失败"
  1144. return
  1145. }
  1146. edbInfoList = append(edbInfoList, fromEdbInfo)
  1147. }
  1148. ok, _ := CheckFormula2(edbInfoList, formulaMap, formula, edbInfoIdBytes)
  1149. if !ok {
  1150. errMsg = "生成计算指标失败,请使用正确的计算公式"
  1151. err = errors.New(errMsg)
  1152. }
  1153. return
  1154. }
  1155. // CalculateByRuleByNine 动态环差规则计算入库
  1156. func CalculateByRuleByNine(formulaStr string, edbInfoList []*data_manage.EdbInfo, edbInfoIdBytes []string) (dataList []*data_manage.EdbDataList, err error) {
  1157. realSaveDataMap := make(map[string]map[int]float64)
  1158. saveDataMap := make(map[string]map[int]float64)
  1159. dateList := make([]string, 0) //日期
  1160. formulaStr = strings.ToUpper(formulaStr)
  1161. // 获取关联指标数据
  1162. for edbInfoIndex, v := range edbInfoList {
  1163. sourceDataList, _, _, tmpErr, _ := GetPredictDataListByPredictEdbInfo(v, "", "", false)
  1164. if tmpErr != nil {
  1165. err = tmpErr
  1166. return
  1167. }
  1168. dataMap := make(map[string]float64)
  1169. for _, dv := range sourceDataList {
  1170. // 实际数据
  1171. if val, ok := realSaveDataMap[dv.DataTime]; ok {
  1172. if _, ok := val[v.EdbInfoId]; !ok {
  1173. val[v.EdbInfoId] = dv.Value
  1174. }
  1175. } else {
  1176. temp := make(map[int]float64)
  1177. temp[v.EdbInfoId] = dv.Value
  1178. realSaveDataMap[dv.DataTime] = temp
  1179. }
  1180. // saveDataMap 待计算的数据
  1181. if val, ok := saveDataMap[dv.DataTime]; ok {
  1182. if _, ok := val[v.EdbInfoId]; !ok {
  1183. val[v.EdbInfoId] = dv.Value
  1184. }
  1185. } else {
  1186. temp2 := make(map[int]float64)
  1187. temp2[v.EdbInfoId] = dv.Value
  1188. saveDataMap[dv.DataTime] = temp2
  1189. }
  1190. // 以第一个指标的日期作为基准日期
  1191. if edbInfoIndex == 0 {
  1192. dateList = append(dateList, dv.DataTime)
  1193. }
  1194. }
  1195. item := new(CalculateItems)
  1196. item.EdbInfoId = v.EdbInfoId
  1197. item.DataMap = dataMap
  1198. }
  1199. //数据处理,将日期内不全的数据做补全
  1200. handleDateSaveDataMap(dateList, realSaveDataMap, saveDataMap, edbInfoList)
  1201. // 添加数据
  1202. dataList = make([]*data_manage.EdbDataList, 0)
  1203. // 计算规则
  1204. formulaMap := CheckFormula(formulaStr)
  1205. existDataMap := make(map[string]string)
  1206. for k, date := range dateList {
  1207. sv := saveDataMap[date]
  1208. //fmt.Println(date, sv)
  1209. formulaFormStr := ReplaceFormula(edbInfoList, sv, formulaMap, formulaStr, edbInfoIdBytes)
  1210. if formulaFormStr == `` {
  1211. //计算公式异常,那么就移除该指标
  1212. continue
  1213. }
  1214. //fmt.Println(fmt.Sprintf("formulaFormStr:%s", formulaFormStr))
  1215. expression := formula.NewExpression(formulaFormStr)
  1216. calResult, tmpErr := expression.Evaluate()
  1217. if tmpErr != nil {
  1218. // 分母为0的报错
  1219. if strings.Contains(tmpErr.Error(), "divide by zero") {
  1220. continue
  1221. }
  1222. err = errors.New("计算失败:Err:" + tmpErr.Error() + ";formulaStr:" + formulaFormStr)
  1223. return
  1224. }
  1225. calVal, tmpErr := calResult.Float64()
  1226. if tmpErr != nil {
  1227. err = errors.New("计算失败:获取计算值失败 Err:" + tmpErr.Error() + ";formulaStr:" + formulaFormStr)
  1228. fmt.Println(err)
  1229. return
  1230. }
  1231. saveValue, _ := decimal.NewFromFloat(calVal).RoundCeil(4).Float64() //utils.SubFloatToString(calVal, 4)
  1232. dataTime, _ := time.Parse(utils.FormatDate, date)
  1233. timestamp := dataTime.UnixNano() / 1e6
  1234. if _, existOk := existDataMap[date]; !existOk {
  1235. tmpPredictEdbRuleData := &data_manage.EdbDataList{
  1236. EdbDataId: k,
  1237. EdbInfoId: 0,
  1238. DataTime: date,
  1239. DataTimestamp: timestamp,
  1240. Value: saveValue,
  1241. }
  1242. dataList = append(dataList, tmpPredictEdbRuleData)
  1243. }
  1244. existDataMap[date] = date
  1245. }
  1246. return
  1247. }