predict_edb.go 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971
  1. package logic
  2. import (
  3. "errors"
  4. "eta/eta_index_lib/models"
  5. "eta/eta_index_lib/utils"
  6. "strconv"
  7. "strings"
  8. "time"
  9. )
  10. // AddPredictEdbInfo 新增预测指标
  11. func AddPredictEdbInfo(sourceEdbInfoId, classifyId int, edbName, dataDateType string, ruleList []models.RuleConfig, minValue, maxValue float64, sysUserId int, sysUserName string) (edbInfo *models.EdbInfo, err error, errMsg string) {
  12. var sourceEdbInfo *models.EdbInfo
  13. // 来源指标信息校验
  14. {
  15. sourceEdbInfo, err = models.GetEdbInfoById(sourceEdbInfoId)
  16. if err != nil && err.Error() != utils.ErrNoRow() {
  17. errMsg = "新增失败"
  18. err = errors.New("获取来源指标失败,Err:" + err.Error())
  19. return
  20. }
  21. if sourceEdbInfo == nil {
  22. errMsg = "找不到该来源指标"
  23. err = errors.New(errMsg)
  24. return
  25. }
  26. //必须是普通的指标
  27. if sourceEdbInfo.EdbInfoType != 0 {
  28. errMsg = "来源指标异常,不是普通的指标"
  29. err = errors.New(errMsg)
  30. return
  31. }
  32. //if !utils.InArrayByStr([]string{"日度", "周度", "月度", "年度"}, sourceEdbInfo.Frequency) {
  33. // errMsg = "预测指标只支持选择日度、周度、月度、年度的指标"
  34. // err = errors.New(errMsg)
  35. // return
  36. //}
  37. }
  38. var classifyInfo *models.EdbClassify
  39. // 来源分类信息校验
  40. {
  41. classifyInfo, err = models.GetEdbClassifyById(classifyId)
  42. if err != nil && err.Error() != utils.ErrNoRow() {
  43. errMsg = "新增失败"
  44. err = errors.New("获取预测指标分类失败,Err:" + err.Error())
  45. return
  46. }
  47. if classifyInfo == nil {
  48. errMsg = "找不到该预测指标分类"
  49. err = errors.New(errMsg)
  50. return
  51. }
  52. //必须是预测指标分类
  53. if classifyInfo.ClassifyType != 1 {
  54. errMsg = "预测指标分类异常,不是预测指标分类"
  55. err = errors.New(errMsg)
  56. return
  57. }
  58. }
  59. edbName = strings.Trim(edbName, " ")
  60. edbCode := sourceEdbInfo.EdbCode + "_" + time.Now().Format(utils.FormatShortDateTimeUnSpace)
  61. //判断指标名称是否存在
  62. var condition string
  63. var pars []interface{}
  64. condition += " AND edb_info_type=? "
  65. pars = append(pars, 1)
  66. condition += " AND edb_name=? "
  67. pars = append(pars, edbName)
  68. count, err := models.GetEdbInfoCountByCondition(condition, pars)
  69. if err != nil {
  70. errMsg = "判断指标名称是否存在失败"
  71. err = errors.New("判断指标名称是否存在失败,Err:" + err.Error())
  72. return
  73. }
  74. if count > 0 {
  75. errMsg = "指标名称已存在,请重新填写"
  76. err = errors.New(errMsg)
  77. return
  78. }
  79. timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
  80. if dataDateType == `` {
  81. dataDateType = `自然日`
  82. }
  83. edbInfo = &models.EdbInfo{
  84. //EdbInfoId: 0,
  85. EdbInfoType: 1,
  86. SourceName: "预测指标",
  87. Source: utils.DATA_SOURCE_PREDICT,
  88. EdbCode: edbCode,
  89. EdbName: edbName,
  90. EdbNameSource: edbName,
  91. Frequency: sourceEdbInfo.Frequency,
  92. Unit: sourceEdbInfo.Unit,
  93. StartDate: sourceEdbInfo.StartDate,
  94. ClassifyId: classifyId,
  95. SysUserId: sysUserId,
  96. SysUserRealName: sysUserName,
  97. UniqueCode: utils.MD5(utils.DATA_PREFIX + "_" + timestamp),
  98. CreateTime: time.Now(),
  99. ModifyTime: time.Now(),
  100. MinValue: minValue,
  101. MaxValue: maxValue,
  102. CalculateFormula: sourceEdbInfo.CalculateFormula,
  103. EdbType: 1,
  104. //Sort: sourceEdbInfo.,
  105. LatestDate: sourceEdbInfo.LatestDate,
  106. LatestValue: sourceEdbInfo.LatestValue,
  107. MoveType: sourceEdbInfo.MoveType,
  108. MoveFrequency: sourceEdbInfo.MoveFrequency,
  109. NoUpdate: sourceEdbInfo.NoUpdate,
  110. ServerUrl: "",
  111. DataDateType: dataDateType,
  112. }
  113. // 关联关系表
  114. calculateMappingList := make([]*models.EdbInfoCalculateMapping, 0)
  115. fromEdbMap := make(map[int]int)
  116. // 源指标关联关系表
  117. calculateMappingItem := &models.EdbInfoCalculateMapping{
  118. //EdbInfoCalculateMappingId: 0,
  119. //EdbInfoId: 0,
  120. Source: edbInfo.Source,
  121. SourceName: edbInfo.SourceName,
  122. EdbCode: edbInfo.EdbCode,
  123. FromEdbInfoId: sourceEdbInfo.EdbInfoId,
  124. FromEdbCode: sourceEdbInfo.EdbCode,
  125. FromEdbName: sourceEdbInfo.EdbName,
  126. FromSource: sourceEdbInfo.Source,
  127. FromSourceName: sourceEdbInfo.SourceName,
  128. //FromTag: "",
  129. Sort: 1,
  130. CreateTime: time.Now(),
  131. ModifyTime: time.Now(),
  132. }
  133. fromEdbMap[sourceEdbInfoId] = sourceEdbInfoId
  134. calculateMappingList = append(calculateMappingList, calculateMappingItem)
  135. // 动态环差 计算列表
  136. calculateRuleMap := make(map[int]models.CalculateRule, 0)
  137. // 预测指标配置
  138. predictEdbConfList := make([]*models.PredictEdbConf, 0)
  139. for ruleIndex, v := range ruleList {
  140. // 预测指标配置
  141. ruleEndDate, tmpErr := time.ParseInLocation(utils.FormatDate, v.EndDate, time.Local)
  142. if tmpErr != nil {
  143. errMsg = "规则配置的截止日期异常,请重新填写"
  144. err = errors.New(errMsg)
  145. return
  146. }
  147. //1:最新,2:固定值,3:同比,4:同差,5:环比,6:环差,7:N期移动均值,8:N期段线性外推值,9:动态环差,10:根据 给定终值后插值 规则获取预测数据,11:根据 季节性 规则获取预测数据,12:根据 移动平均同比 规则获取预测数据
  148. // 环比、环差、动态环差、季节性、移动平均同比不支持年度
  149. if sourceEdbInfo.Frequency == "年度" && utils.InArrayByInt([]int{5, 6, 11, 12}, v.RuleType) {
  150. errMsg = "环比、环差、动态环差、季节性、移动平均同比不支持年度指标"
  151. err = errors.New(errMsg)
  152. return
  153. }
  154. switch v.RuleType {
  155. case 8: //N期段线性外推值
  156. valInt, tmpErr := strconv.Atoi(v.Value)
  157. if tmpErr != nil {
  158. errMsg = "N期段线性外推值的N值异常"
  159. err = errors.New(errMsg)
  160. return
  161. }
  162. if valInt <= 1 {
  163. errMsg = "N期段线性外推值的N值必须大于1"
  164. err = errors.New(errMsg)
  165. return
  166. }
  167. case 9: //9:动态环差
  168. if v.Value == "" {
  169. errMsg = "请填写计算规则"
  170. err = errors.New(errMsg)
  171. return
  172. }
  173. formula := v.Value
  174. formula = strings.Replace(formula, "(", "(", -1)
  175. formula = strings.Replace(formula, ")", ")", -1)
  176. formula = strings.Replace(formula, ",", ",", -1)
  177. formula = strings.Replace(formula, "。", ".", -1)
  178. formula = strings.Replace(formula, "%", "*0.01", -1)
  179. v.Value = formula
  180. //检验公式
  181. var formulaStr string
  182. var edbInfoIdBytes []string
  183. for _, tmpEdbInfoId := range v.EdbInfoIdArr {
  184. formulaStr += tmpEdbInfoId.FromTag + ","
  185. edbInfoIdBytes = append(edbInfoIdBytes, tmpEdbInfoId.FromTag)
  186. }
  187. formulaSlice, tErr := utils.CheckFormulaJson(formula)
  188. if tErr != nil {
  189. errMsg = "公式格式错误,请重新填写"
  190. err = errors.New(errMsg)
  191. return
  192. }
  193. for _, fm := range formulaSlice {
  194. formulaMap := utils.CheckFormula(fm)
  195. for _, f := range formulaMap {
  196. if !strings.Contains(formulaStr, f) {
  197. errMsg = "公式错误,请重新填写"
  198. err = errors.New(errMsg)
  199. return
  200. }
  201. }
  202. }
  203. //关联的指标信息
  204. edbInfoList := make([]*models.EdbInfo, 0)
  205. // 动态环差规则 关系表
  206. trendsMappingList := make([]*models.PredictEdbConfCalculateMapping, 0)
  207. for k, tmpEdbInfoId := range v.EdbInfoIdArr {
  208. fromEdbInfo, tmpErr := models.GetEdbInfoById(tmpEdbInfoId.EdbInfoId)
  209. if tmpErr != nil {
  210. err = tmpErr
  211. if err.Error() == utils.ErrNoRow() {
  212. errMsg = "指标 " + strconv.Itoa(tmpEdbInfoId.EdbInfoId) + " 不存在"
  213. err = errors.New(errMsg)
  214. return
  215. }
  216. errMsg = "获取指标失败:Err:" + err.Error()
  217. err = errors.New(errMsg)
  218. return
  219. }
  220. edbInfoList = append(edbInfoList, fromEdbInfo)
  221. //总的 预测指标与所有相关联指标的关系表(不仅仅该条规则)
  222. {
  223. if _, ok := fromEdbMap[tmpEdbInfoId.EdbInfoId]; !ok {
  224. fromEdbMap[tmpEdbInfoId.EdbInfoId] = tmpEdbInfoId.EdbInfoId
  225. calculateMappingItem := &models.EdbInfoCalculateMapping{
  226. EdbInfoCalculateMappingId: 0,
  227. EdbInfoId: 0,
  228. Source: utils.DATA_SOURCE_CALCULATE,
  229. SourceName: "指标运算",
  230. EdbCode: "",
  231. FromEdbInfoId: fromEdbInfo.EdbInfoId,
  232. FromEdbCode: fromEdbInfo.EdbCode,
  233. FromEdbName: fromEdbInfo.EdbName,
  234. FromSource: fromEdbInfo.Source,
  235. FromSourceName: fromEdbInfo.SourceName,
  236. //FromTag: tmpEdbInfoId.FromTag,
  237. Sort: k + 1,
  238. CreateTime: time.Now(),
  239. ModifyTime: time.Now(),
  240. }
  241. calculateMappingList = append(calculateMappingList, calculateMappingItem)
  242. }
  243. }
  244. // 动态环差规则 关系表
  245. tmpPredictEdbConfCalculateMapping := &models.PredictEdbConfCalculateMapping{
  246. //PredictEdbConfCalculateMappingId: 0,
  247. EdbInfoId: 0,
  248. ConfigId: 0,
  249. FromEdbInfoId: fromEdbInfo.EdbInfoId,
  250. FromEdbCode: fromEdbInfo.EdbCode,
  251. FromEdbName: fromEdbInfo.EdbName,
  252. FromSource: fromEdbInfo.Source,
  253. FromSourceName: fromEdbInfo.SourceName,
  254. FromTag: tmpEdbInfoId.FromTag,
  255. Sort: k + 1,
  256. CreateTime: time.Now(),
  257. ModifyTime: time.Now(),
  258. }
  259. trendsMappingList = append(trendsMappingList, tmpPredictEdbConfCalculateMapping)
  260. }
  261. for _, f := range formulaSlice {
  262. formulaMap := utils.CheckFormula(f)
  263. //预先计算,判断公式是否正常
  264. ok, _ := models.CheckFormula2(edbInfoList, formulaMap, f, edbInfoIdBytes)
  265. if !ok {
  266. errMsg = "生成计算指标失败,请使用正确的计算公式"
  267. err = errors.New(errMsg)
  268. return
  269. }
  270. }
  271. calculateRuleMap[ruleIndex] = models.CalculateRule{
  272. TrendsCalculateMappingList: trendsMappingList,
  273. EdbInfoList: edbInfoList,
  274. EdbInfoIdBytes: edbInfoIdBytes,
  275. Formula: formula,
  276. RuleType: v.RuleType,
  277. EndDate: v.EndDate,
  278. EdbInfoIdArr: v.EdbInfoIdArr,
  279. }
  280. case 14: //14:根据 一元线性拟合 规则获取预测数据
  281. if v.Value == "" {
  282. errMsg = "请填写一元线性拟合规则"
  283. err = errors.New(errMsg)
  284. return
  285. }
  286. //关联的指标信息
  287. edbInfoList := make([]*models.EdbInfo, 0)
  288. // 动态环差规则 关系表
  289. trendsMappingList := make([]*models.PredictEdbConfCalculateMapping, 0)
  290. for k, tmpEdbInfoId := range v.EdbInfoIdArr {
  291. fromEdbInfo, tmpErr := models.GetEdbInfoById(tmpEdbInfoId.EdbInfoId)
  292. if tmpErr != nil {
  293. err = tmpErr
  294. if err.Error() == utils.ErrNoRow() {
  295. errMsg = "指标 " + strconv.Itoa(tmpEdbInfoId.EdbInfoId) + " 不存在"
  296. err = errors.New(errMsg)
  297. return
  298. }
  299. errMsg = "获取指标失败:Err:" + err.Error()
  300. err = errors.New(errMsg)
  301. return
  302. }
  303. edbInfoList = append(edbInfoList, fromEdbInfo)
  304. //总的 预测指标与所有相关联指标的关系表(不仅仅该条规则)
  305. {
  306. if _, ok := fromEdbMap[tmpEdbInfoId.EdbInfoId]; !ok {
  307. fromEdbMap[tmpEdbInfoId.EdbInfoId] = tmpEdbInfoId.EdbInfoId
  308. tmpCalculateMappingItem := &models.EdbInfoCalculateMapping{
  309. EdbInfoCalculateMappingId: 0,
  310. EdbInfoId: 0,
  311. Source: utils.DATA_SOURCE_CALCULATE,
  312. SourceName: "指标运算",
  313. EdbCode: "",
  314. FromEdbInfoId: fromEdbInfo.EdbInfoId,
  315. FromEdbCode: fromEdbInfo.EdbCode,
  316. FromEdbName: fromEdbInfo.EdbName,
  317. FromSource: fromEdbInfo.Source,
  318. FromSourceName: fromEdbInfo.SourceName,
  319. //FromTag: tmpEdbInfoId.FromTag,
  320. Sort: k + 1,
  321. CreateTime: time.Now(),
  322. ModifyTime: time.Now(),
  323. }
  324. calculateMappingList = append(calculateMappingList, tmpCalculateMappingItem)
  325. }
  326. }
  327. // 动态环差规则 关系表
  328. tmpPredictEdbConfCalculateMapping := &models.PredictEdbConfCalculateMapping{
  329. //PredictEdbConfCalculateMappingId: 0,
  330. EdbInfoId: 0,
  331. ConfigId: 0,
  332. FromEdbInfoId: fromEdbInfo.EdbInfoId,
  333. FromEdbCode: fromEdbInfo.EdbCode,
  334. FromEdbName: fromEdbInfo.EdbName,
  335. FromSource: fromEdbInfo.Source,
  336. FromSourceName: fromEdbInfo.SourceName,
  337. FromTag: tmpEdbInfoId.FromTag,
  338. Sort: k + 1,
  339. CreateTime: time.Now(),
  340. ModifyTime: time.Now(),
  341. }
  342. trendsMappingList = append(trendsMappingList, tmpPredictEdbConfCalculateMapping)
  343. }
  344. calculateRuleMap[ruleIndex] = models.CalculateRule{
  345. TrendsCalculateMappingList: trendsMappingList,
  346. EdbInfoList: edbInfoList,
  347. //EdbInfoIdBytes: edbInfoIdBytes,
  348. //Formula: formula,
  349. RuleType: v.RuleType,
  350. EndDate: v.EndDate,
  351. EdbInfoIdArr: v.EdbInfoIdArr,
  352. }
  353. }
  354. tmpPredictEdbConf := &models.PredictEdbConf{
  355. PredictEdbInfoId: 0,
  356. SourceEdbInfoId: sourceEdbInfoId,
  357. RuleType: v.RuleType,
  358. //FixedValue: v.Value,
  359. Value: v.Value,
  360. EndDate: ruleEndDate,
  361. ModifyTime: time.Now(),
  362. CreateTime: time.Now(),
  363. }
  364. edbInfo.EndDate = v.EndDate
  365. predictEdbConfList = append(predictEdbConfList, tmpPredictEdbConf)
  366. }
  367. err, errMsg = models.AddPredictEdb(edbInfo, calculateMappingList, predictEdbConfList, calculateRuleMap)
  368. return
  369. }
  370. // EditPredictEdbInfo 编辑预测指标
  371. func EditPredictEdbInfo(edbInfoId, classifyId int, edbName, dataDateType string, ruleList []models.RuleConfig, minValue, maxValue float64) (edbInfo *models.EdbInfo, err error, errMsg string) {
  372. // 指标信息校验
  373. {
  374. edbInfo, err = models.GetEdbInfoById(edbInfoId)
  375. if err != nil && err.Error() != utils.ErrNoRow() {
  376. errMsg = "修改失败"
  377. err = errors.New("获取预测指标失败,Err:" + err.Error())
  378. return
  379. }
  380. if edbInfo == nil {
  381. errMsg = "找不到该预测指标"
  382. err = errors.New(errMsg)
  383. return
  384. }
  385. //必须是普通的指标
  386. if edbInfo.EdbInfoType != 1 {
  387. errMsg = "指标异常,不是预测指标"
  388. err = errors.New(errMsg)
  389. return
  390. }
  391. }
  392. var predictEdbConf *models.PredictEdbConf
  393. // 指标配置信息校验
  394. {
  395. // 查找该预测指标配置
  396. predictEdbConfList, tmpErr := models.GetPredictEdbConfListById(edbInfo.EdbInfoId)
  397. if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
  398. errMsg = "修改失败"
  399. err = errors.New("获取预测指标配置信息失败,Err:" + tmpErr.Error())
  400. return
  401. }
  402. if len(predictEdbConfList) == 0 {
  403. errMsg = "找不到该预测指标配置"
  404. err = errors.New(errMsg)
  405. return
  406. }
  407. predictEdbConf = predictEdbConfList[0]
  408. }
  409. //判断指标名称是否存在
  410. var condition string
  411. var pars []interface{}
  412. condition += " AND edb_info_id<>? "
  413. pars = append(pars, edbInfoId)
  414. condition += " AND edb_info_type=? "
  415. pars = append(pars, 1)
  416. condition += " AND edb_name=? "
  417. pars = append(pars, edbName)
  418. count, err := models.GetEdbInfoCountByCondition(condition, pars)
  419. if err != nil {
  420. errMsg = "判断指标名称是否存在失败"
  421. err = errors.New("判断指标名称是否存在失败,Err:" + err.Error())
  422. return
  423. }
  424. if count > 0 {
  425. errMsg = "指标名称已存在,请重新填写"
  426. err = errors.New(errMsg)
  427. return
  428. }
  429. if dataDateType == `` {
  430. dataDateType = `自然日`
  431. }
  432. edbInfo.EdbName = edbName
  433. edbInfo.EdbNameSource = edbName
  434. edbInfo.ClassifyId = classifyId
  435. edbInfo.MinValue = minValue
  436. edbInfo.MaxValue = maxValue
  437. edbInfo.DataDateType = dataDateType
  438. edbInfo.ModifyTime = time.Now()
  439. updateEdbInfoCol := []string{"EdbName", "EdbNameSource", "ClassifyId", "EndDate", "MinValue", "MaxValue", "DataDateType", "ModifyTime"}
  440. var sourceEdbInfo *models.EdbInfo
  441. // 来源指标信息校验
  442. {
  443. sourceEdbInfo, err = models.GetEdbInfoById(predictEdbConf.SourceEdbInfoId)
  444. if err != nil && err.Error() != utils.ErrNoRow() {
  445. errMsg = "新增失败"
  446. err = errors.New("获取来源指标失败,Err:" + err.Error())
  447. return
  448. }
  449. if sourceEdbInfo == nil {
  450. errMsg = "找不到该来源指标"
  451. err = errors.New(errMsg)
  452. return
  453. }
  454. //必须是普通的指标
  455. if sourceEdbInfo.EdbInfoType != 0 {
  456. errMsg = "来源指标异常,不是普通的指标"
  457. err = errors.New(errMsg)
  458. return
  459. }
  460. //if !utils.InArrayByStr([]string{"日度", "周度", "月度", "年度"}, sourceEdbInfo.Frequency) {
  461. // errMsg = "预测指标只支持选择日度、周度、月度、年度的指标"
  462. // err = errors.New(errMsg)
  463. // return
  464. //}
  465. }
  466. // 预测指标配置
  467. // 关联关系表
  468. calculateMappingList := make([]*models.EdbInfoCalculateMapping, 0)
  469. fromEdbMap := make(map[int]int)
  470. // 源指标关联关系表
  471. calculateMappingItem := &models.EdbInfoCalculateMapping{
  472. //EdbInfoCalculateMappingId: 0,
  473. EdbInfoId: edbInfoId,
  474. Source: edbInfo.Source,
  475. SourceName: edbInfo.SourceName,
  476. EdbCode: edbInfo.EdbCode,
  477. FromEdbInfoId: sourceEdbInfo.EdbInfoId,
  478. FromEdbCode: sourceEdbInfo.EdbCode,
  479. FromEdbName: sourceEdbInfo.EdbName,
  480. FromSource: sourceEdbInfo.Source,
  481. FromSourceName: sourceEdbInfo.SourceName,
  482. //FromTag: "",
  483. Sort: 1,
  484. CreateTime: time.Now(),
  485. ModifyTime: time.Now(),
  486. }
  487. fromEdbMap[sourceEdbInfo.EdbInfoId] = sourceEdbInfo.EdbInfoId
  488. calculateMappingList = append(calculateMappingList, calculateMappingItem)
  489. // 动态环差 计算列表
  490. calculateRuleMap := make(map[int]models.CalculateRule, 0)
  491. // 预测指标配置
  492. predictEdbConfList := make([]*models.PredictEdbConf, 0)
  493. for ruleIndex, v := range ruleList {
  494. // 预测指标配置
  495. ruleEndDate, tmpErr := time.ParseInLocation(utils.FormatDate, v.EndDate, time.Local)
  496. if tmpErr != nil {
  497. errMsg = "规则配置的截止日期异常,请重新填写"
  498. err = errors.New(errMsg)
  499. return
  500. }
  501. //1:最新,2:固定值,3:同比,4:同差,5:环比,6:环差,7:N期移动均值,8:N期段线性外推值,9:动态环差,10:根据 给定终值后插值 规则获取预测数据,11:根据 季节性 规则获取预测数据,12:根据 移动平均同比 规则获取预测数据
  502. // 环比、环差、动态环差、季节性、移动平均同比不支持年度
  503. if sourceEdbInfo.Frequency == "年度" && utils.InArrayByInt([]int{5, 6, 11, 12}, v.RuleType) {
  504. errMsg = "环比、环差、动态环差、季节性、移动平均同比不支持年度指标"
  505. err = errors.New(errMsg)
  506. return
  507. }
  508. switch v.RuleType {
  509. case 8: //N期段线性外推值
  510. valInt, tmpErr := strconv.Atoi(v.Value)
  511. if tmpErr != nil {
  512. errMsg = "N期段线性外推值的N值异常"
  513. err = errors.New(errMsg)
  514. return
  515. }
  516. if valInt <= 1 {
  517. errMsg = "N期段线性外推值的N值必须大于1"
  518. err = errors.New(errMsg)
  519. return
  520. }
  521. case 9: //9:动态环差
  522. if v.Value == "" {
  523. errMsg = "请填写计算规则"
  524. err = errors.New(errMsg)
  525. return
  526. }
  527. formula := v.Value
  528. formula = strings.Replace(formula, "(", "(", -1)
  529. formula = strings.Replace(formula, ")", ")", -1)
  530. formula = strings.Replace(formula, ",", ",", -1)
  531. formula = strings.Replace(formula, "。", ".", -1)
  532. formula = strings.Replace(formula, "%", "*0.01", -1)
  533. v.Value = formula
  534. //检验公式
  535. var formulaStr string
  536. var edbInfoIdBytes []string
  537. for _, tmpEdbInfoId := range v.EdbInfoIdArr {
  538. formulaStr += tmpEdbInfoId.FromTag + ","
  539. edbInfoIdBytes = append(edbInfoIdBytes, tmpEdbInfoId.FromTag)
  540. }
  541. formulaSlice, tErr := utils.CheckFormulaJson(formula)
  542. if tErr != nil {
  543. errMsg = "公式格式错误,请重新填写"
  544. err = errors.New(errMsg)
  545. return
  546. }
  547. for _, fm := range formulaSlice {
  548. formulaMap := utils.CheckFormula(fm)
  549. for _, f := range formulaMap {
  550. if !strings.Contains(formulaStr, f) {
  551. errMsg = "公式错误,请重新填写"
  552. err = errors.New(errMsg)
  553. return
  554. }
  555. }
  556. }
  557. //关联的指标信息
  558. edbInfoList := make([]*models.EdbInfo, 0)
  559. // 动态环差规则 关系表
  560. trendsMappingList := make([]*models.PredictEdbConfCalculateMapping, 0)
  561. for k, tmpEdbInfoId := range v.EdbInfoIdArr {
  562. fromEdbInfo, tmpErr := models.GetEdbInfoById(tmpEdbInfoId.EdbInfoId)
  563. if tmpErr != nil {
  564. err = tmpErr
  565. if err.Error() == utils.ErrNoRow() {
  566. errMsg = "指标 " + strconv.Itoa(tmpEdbInfoId.EdbInfoId) + " 不存在"
  567. err = errors.New(errMsg)
  568. return
  569. }
  570. errMsg = "获取指标失败:Err:" + err.Error()
  571. err = errors.New(errMsg)
  572. return
  573. }
  574. edbInfoList = append(edbInfoList, fromEdbInfo)
  575. //总的 预测指标与所有相关联指标的关系表(不仅仅该条规则)
  576. {
  577. if _, ok := fromEdbMap[tmpEdbInfoId.EdbInfoId]; !ok {
  578. fromEdbMap[tmpEdbInfoId.EdbInfoId] = tmpEdbInfoId.EdbInfoId
  579. calculateMappingItem := &models.EdbInfoCalculateMapping{
  580. EdbInfoCalculateMappingId: 0,
  581. EdbInfoId: edbInfoId,
  582. Source: utils.DATA_SOURCE_CALCULATE,
  583. SourceName: "指标运算",
  584. EdbCode: "",
  585. FromEdbInfoId: fromEdbInfo.EdbInfoId,
  586. FromEdbCode: fromEdbInfo.EdbCode,
  587. FromEdbName: fromEdbInfo.EdbName,
  588. FromSource: fromEdbInfo.Source,
  589. FromSourceName: fromEdbInfo.SourceName,
  590. //FromTag: tmpEdbInfoId.FromTag,
  591. Sort: k + 1,
  592. CreateTime: time.Now(),
  593. ModifyTime: time.Now(),
  594. }
  595. calculateMappingList = append(calculateMappingList, calculateMappingItem)
  596. }
  597. }
  598. // 动态环差规则 关系表
  599. tmpPredictEdbConfCalculateMapping := &models.PredictEdbConfCalculateMapping{
  600. //PredictEdbConfCalculateMappingId: 0,
  601. EdbInfoId: edbInfoId,
  602. ConfigId: 0,
  603. FromEdbInfoId: fromEdbInfo.EdbInfoId,
  604. FromEdbCode: fromEdbInfo.EdbCode,
  605. FromEdbName: fromEdbInfo.EdbName,
  606. FromSource: fromEdbInfo.Source,
  607. FromSourceName: fromEdbInfo.SourceName,
  608. FromTag: tmpEdbInfoId.FromTag,
  609. Sort: k + 1,
  610. CreateTime: time.Now(),
  611. ModifyTime: time.Now(),
  612. }
  613. trendsMappingList = append(trendsMappingList, tmpPredictEdbConfCalculateMapping)
  614. }
  615. for _, f := range formulaSlice {
  616. formulaMap := utils.CheckFormula(f)
  617. //预先计算,判断公式是否正常
  618. ok, _ := models.CheckFormula2(edbInfoList, formulaMap, f, edbInfoIdBytes)
  619. if !ok {
  620. errMsg = "生成计算指标失败,请使用正确的计算公式"
  621. err = errors.New(errMsg)
  622. return
  623. }
  624. }
  625. calculateRuleMap[ruleIndex] = models.CalculateRule{
  626. TrendsCalculateMappingList: trendsMappingList,
  627. EdbInfoList: edbInfoList,
  628. EdbInfoIdBytes: edbInfoIdBytes,
  629. Formula: formula,
  630. RuleType: v.RuleType,
  631. EndDate: v.EndDate,
  632. EdbInfoIdArr: v.EdbInfoIdArr,
  633. }
  634. case 14: //14:根据 一元线性拟合 规则获取预测数据
  635. if v.Value == "" {
  636. errMsg = "请填写一元线性拟合规则"
  637. err = errors.New(errMsg)
  638. return
  639. }
  640. //关联的指标信息
  641. edbInfoList := make([]*models.EdbInfo, 0)
  642. // 动态环差规则 关系表
  643. trendsMappingList := make([]*models.PredictEdbConfCalculateMapping, 0)
  644. for k, tmpEdbInfoId := range v.EdbInfoIdArr {
  645. fromEdbInfo, tmpErr := models.GetEdbInfoById(tmpEdbInfoId.EdbInfoId)
  646. if tmpErr != nil {
  647. err = tmpErr
  648. if err.Error() == utils.ErrNoRow() {
  649. errMsg = "指标 " + strconv.Itoa(tmpEdbInfoId.EdbInfoId) + " 不存在"
  650. err = errors.New(errMsg)
  651. return
  652. }
  653. errMsg = "获取指标失败:Err:" + err.Error()
  654. err = errors.New(errMsg)
  655. return
  656. }
  657. edbInfoList = append(edbInfoList, fromEdbInfo)
  658. //总的 预测指标与所有相关联指标的关系表(不仅仅该条规则)
  659. {
  660. if _, ok := fromEdbMap[tmpEdbInfoId.EdbInfoId]; !ok {
  661. fromEdbMap[tmpEdbInfoId.EdbInfoId] = tmpEdbInfoId.EdbInfoId
  662. tmpCalculateMappingItem := &models.EdbInfoCalculateMapping{
  663. EdbInfoCalculateMappingId: 0,
  664. EdbInfoId: 0,
  665. Source: utils.DATA_SOURCE_CALCULATE,
  666. SourceName: "指标运算",
  667. EdbCode: "",
  668. FromEdbInfoId: fromEdbInfo.EdbInfoId,
  669. FromEdbCode: fromEdbInfo.EdbCode,
  670. FromEdbName: fromEdbInfo.EdbName,
  671. FromSource: fromEdbInfo.Source,
  672. FromSourceName: fromEdbInfo.SourceName,
  673. //FromTag: tmpEdbInfoId.FromTag,
  674. Sort: k + 1,
  675. CreateTime: time.Now(),
  676. ModifyTime: time.Now(),
  677. }
  678. calculateMappingList = append(calculateMappingList, tmpCalculateMappingItem)
  679. }
  680. }
  681. // 动态环差规则 关系表
  682. tmpPredictEdbConfCalculateMapping := &models.PredictEdbConfCalculateMapping{
  683. //PredictEdbConfCalculateMappingId: 0,
  684. EdbInfoId: 0,
  685. ConfigId: 0,
  686. FromEdbInfoId: fromEdbInfo.EdbInfoId,
  687. FromEdbCode: fromEdbInfo.EdbCode,
  688. FromEdbName: fromEdbInfo.EdbName,
  689. FromSource: fromEdbInfo.Source,
  690. FromSourceName: fromEdbInfo.SourceName,
  691. FromTag: tmpEdbInfoId.FromTag,
  692. Sort: k + 1,
  693. CreateTime: time.Now(),
  694. ModifyTime: time.Now(),
  695. }
  696. trendsMappingList = append(trendsMappingList, tmpPredictEdbConfCalculateMapping)
  697. }
  698. calculateRuleMap[ruleIndex] = models.CalculateRule{
  699. TrendsCalculateMappingList: trendsMappingList,
  700. EdbInfoList: edbInfoList,
  701. //EdbInfoIdBytes: edbInfoIdBytes,
  702. //Formula: formula,
  703. RuleType: v.RuleType,
  704. EndDate: v.EndDate,
  705. EdbInfoIdArr: v.EdbInfoIdArr,
  706. }
  707. }
  708. tmpPredictEdbConf := &models.PredictEdbConf{
  709. PredictEdbInfoId: edbInfoId,
  710. SourceEdbInfoId: sourceEdbInfo.EdbInfoId,
  711. RuleType: v.RuleType,
  712. //FixedValue: v.Value,
  713. Value: v.Value,
  714. EndDate: ruleEndDate,
  715. ModifyTime: time.Now(),
  716. CreateTime: time.Now(),
  717. }
  718. edbInfo.EndDate = v.EndDate
  719. predictEdbConfList = append(predictEdbConfList, tmpPredictEdbConf)
  720. }
  721. err, errMsg = models.EditPredictEdb(edbInfo, updateEdbInfoCol, calculateMappingList, predictEdbConfList, calculateRuleMap)
  722. return
  723. }
  724. // RefreshPredictEdbInfo 更新基础预测指标规则中的动态数据
  725. func RefreshPredictEdbInfo(edbInfoId int) (edbInfo *models.EdbInfo, err error, errMsg string) {
  726. // 指标信息校验
  727. {
  728. edbInfo, err = models.GetEdbInfoById(edbInfoId)
  729. if err != nil && err.Error() != utils.ErrNoRow() {
  730. errMsg = "刷新失败"
  731. err = errors.New("获取预测指标失败,Err:" + err.Error())
  732. return
  733. }
  734. if edbInfo == nil {
  735. errMsg = "找不到该预测指标"
  736. err = nil
  737. return
  738. }
  739. //必须是普通的指标
  740. if edbInfo.EdbInfoType != 1 {
  741. errMsg = "指标异常,不是预测指标"
  742. return
  743. }
  744. }
  745. // 配置 与 指标的 关联关系表
  746. list, err := models.GetPredictEdbConfCalculateMappingListByEdbInfoId(edbInfoId)
  747. if err != nil {
  748. return
  749. }
  750. // 没有关联指标,不需要刷新
  751. if len(list) <= 0 {
  752. return
  753. }
  754. // 配置关联的指标信息
  755. predictEdbConfCalculateMappingListMap := make(map[int][]*models.PredictEdbConfCalculateMapping)
  756. configIdList := make([]int, 0) //关联配置id
  757. edbInfoIdList := make([]int, 0) //关联指标配置id
  758. edbInfoIdMap := make(map[int]int, 0) //关联指标配置map
  759. for _, v := range list {
  760. configList, ok := predictEdbConfCalculateMappingListMap[v.ConfigId]
  761. if !ok {
  762. configList = make([]*models.PredictEdbConfCalculateMapping, 0)
  763. configIdList = append(configIdList, v.ConfigId)
  764. }
  765. if _, ok := edbInfoIdMap[v.FromEdbInfoId]; !ok {
  766. edbInfoIdList = append(edbInfoIdList, v.FromEdbInfoId)
  767. }
  768. configList = append(configList, v)
  769. predictEdbConfCalculateMappingListMap[v.ConfigId] = configList
  770. }
  771. predictEdbConfList, err := models.GetPredictEdbConfListByConfigIdList(configIdList)
  772. if err != nil {
  773. errMsg = "刷新失败"
  774. err = errors.New("获取预测指标配置信息失败,Err:" + err.Error())
  775. return
  776. }
  777. if len(predictEdbConfList) == 0 {
  778. errMsg = "找不到该预测指标配置"
  779. err = nil
  780. return
  781. }
  782. // 指标信息
  783. edbInfoList, err := models.GetEdbInfoByIdList(edbInfoIdList)
  784. if err != nil {
  785. err = errors.New("获取关联指标失败,Err:" + err.Error())
  786. return
  787. }
  788. // 指标信息map
  789. edbInfoListMap := make(map[int]*models.EdbInfo)
  790. for _, v := range edbInfoList {
  791. edbInfoListMap[v.EdbInfoId] = v
  792. }
  793. predictEdbConfAndDataList := make([]*models.PredictEdbConfAndData, 0)
  794. // 刷新所有的规则
  795. for _, v := range predictEdbConfList {
  796. // 每次规则计算的时候,产生的临时数据
  797. resultDataList := make([]*models.EdbInfoSearchData, 0)
  798. switch v.RuleType {
  799. case 9: //动态环差值
  800. if v.Value == "" {
  801. errMsg = "请填写计算规则"
  802. return
  803. }
  804. // todo 动态环差的空值类型处理
  805. formula := v.Value
  806. // 动态环差规则 关系表
  807. trendsMappingList := predictEdbConfCalculateMappingListMap[v.ConfigId]
  808. // 关联标签
  809. edbInfoIdArr := make([]models.EdbInfoFromTag, 0)
  810. //关联的指标信息
  811. edbInfoList := make([]*models.EdbInfo, 0)
  812. for _, trendsMapping := range trendsMappingList {
  813. tmpEdbInfo, ok := edbInfoListMap[trendsMapping.FromEdbInfoId]
  814. if ok {
  815. edbInfoList = append(edbInfoList, tmpEdbInfo)
  816. }
  817. // 关联标签
  818. edbInfoIdArr = append(edbInfoIdArr, models.EdbInfoFromTag{
  819. EdbInfoId: trendsMapping.FromEdbInfoId,
  820. FromTag: trendsMapping.FromTag,
  821. })
  822. }
  823. //检验公式
  824. var formulaStr string
  825. var edbInfoIdBytes []string
  826. for _, tmpEdbInfoId := range edbInfoIdArr {
  827. formulaStr += tmpEdbInfoId.FromTag + ","
  828. edbInfoIdBytes = append(edbInfoIdBytes, tmpEdbInfoId.FromTag)
  829. }
  830. formulaSlice, tErr := utils.CheckFormulaJson(formula)
  831. if tErr != nil {
  832. errMsg = "公式格式错误,请重新填写"
  833. err = errors.New(errMsg)
  834. return
  835. }
  836. for _, fm := range formulaSlice {
  837. formulaMap := utils.CheckFormula(fm)
  838. for _, f := range formulaMap {
  839. if !strings.Contains(formulaStr, f) {
  840. errMsg = "公式错误,请重新填写"
  841. err = errors.New(errMsg)
  842. return
  843. }
  844. }
  845. //预先计算,判断公式是否正常
  846. ok, _ := models.CheckFormula2(edbInfoList, formulaMap, fm, edbInfoIdBytes)
  847. if !ok {
  848. errMsg = "生成计算指标失败,请使用正确的计算公式"
  849. return
  850. }
  851. }
  852. rule := models.CalculateRule{
  853. EdbInfoId: v.PredictEdbInfoId,
  854. ConfigId: v.ConfigId,
  855. TrendsCalculateMappingList: trendsMappingList,
  856. EdbInfoList: edbInfoList,
  857. EdbInfoIdBytes: edbInfoIdBytes,
  858. Formula: formula,
  859. RuleType: v.RuleType,
  860. EndDate: v.EndDate.Format(utils.FormatDate),
  861. EdbInfoIdArr: edbInfoIdArr,
  862. }
  863. resultDataList, err = models.RefreshCalculateByRuleBy9(rule)
  864. if err != nil {
  865. return
  866. }
  867. case 14: //14:根据 一元线性拟合 规则获取预测数据
  868. if v.Value == "" {
  869. errMsg = "一元线性拟合规则信息未配置"
  870. return
  871. }
  872. err, errMsg = models.RefreshCalculateByRuleByLineNh(*edbInfo, predictEdbConfAndDataList, *v)
  873. if err != nil {
  874. return
  875. }
  876. }
  877. // 规则配置(含数据)
  878. tmpPredictEdbConfAndData := &models.PredictEdbConfAndData{
  879. ConfigId: 0,
  880. PredictEdbInfoId: 0,
  881. SourceEdbInfoId: v.SourceEdbInfoId,
  882. RuleType: v.RuleType,
  883. FixedValue: v.FixedValue,
  884. Value: v.Value,
  885. EndDate: v.EndDate,
  886. ModifyTime: v.ModifyTime,
  887. CreateTime: v.CreateTime,
  888. DataList: resultDataList,
  889. }
  890. predictEdbConfAndDataList = append(predictEdbConfAndDataList, tmpPredictEdbConfAndData)
  891. }
  892. return
  893. }