predict_edb.go 30 KB

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