package kpi_c_title import ( "fmt" "net/http" "regexp" "sort" "strconv" "strings" "time" "be.ems/lib/log" "be.ems/lib/services" "be.ems/src/framework/database/db" "be.ems/src/framework/reqctx" "github.com/gin-gonic/gin" ) // get customize kpi total and list func (k *KpiCTitle) GetToalList(c *gin.Context) { var titles []KpiCTitle var conditions []string var params []any i18n := reqctx.AcceptLanguage(c) var querys KpiCTitleQuery if err := c.ShouldBindQuery(&querys); err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } dbg := db.DB("").Model(&KpiCTitle{}) // construct condition to get if neType := querys.NeType; neType != "" { conditions = append(conditions, "ne_type = ?") params = append(params, strings.ToUpper(neType)) } if status := querys.Status; status != "" { conditions = append(conditions, "status = ?") params = append(params, status) } else { conditions = append(conditions, "status != '2'") } whereSql := "" if len(conditions) > 0 { whereSql += strings.Join(conditions, " and ") dbg = dbg.Where(whereSql, params...) } // Get total number var total int64 = 0 if err := dbg.Count(&total).Error; err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } // page number and size if pageSize := querys.PageSize; pageSize > 0 { dbg = dbg.Limit(pageSize) if pageNum := querys.PageNum; pageNum > 0 { dbg = dbg.Offset((pageNum - 1) * pageSize) } } // order by if sortField, sortOrder := querys.SortField, querys.SortOrder; sortField != "" && sortOrder != "" { orderBy := fmt.Sprintf("%s %s", sortField, sortOrder) dbg = dbg.Order(orderBy) } if err := dbg.Find(&titles).Error; err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } k.expressionAlias(titles, i18n) c.JSON(http.StatusOK, services.TotalDataResp(titles, total)) //c.JSON(http.StatusOK, titles) } func (k *KpiCTitle) Get(c *gin.Context) { var titles []KpiCTitle var conditions []string var params []any i18n := reqctx.AcceptLanguage(c) // construct condition to get if neType := c.Query("neType"); neType != "" { conditions = append(conditions, "ne_type = ?") params = append(params, strings.ToUpper(neType)) } if status := c.Query("status"); status != "" { conditions = append(conditions, "status = ?") params = append(params, status) } else { conditions = append(conditions, "status != '2'") } whereSql := "" if len(conditions) > 0 { whereSql += strings.Join(conditions, " and ") } if err := db.DB("").Where(whereSql, params...).Find(&titles).Error; err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } k.expressionAlias(titles, i18n) c.JSON(http.StatusOK, services.DataResp(titles)) //c.JSON(http.StatusOK, titles) } // alias customized kpi expression with cn/en title func (k *KpiCTitle) expressionAlias(titles []KpiCTitle, i18n string) { var title *KpiCTitle for i := 0; i < len(titles); i++ { title = &titles[i] title.ExprAlias = *title.Expression re := regexp.MustCompile(`'([^']+)'`) matches := re.FindAllStringSubmatch(title.ExprAlias, -1) for _, match := range matches { var alias, sql string if i18n == "zh" { sql = fmt.Sprintf("SELECT cn_title FROM kpi_title WHERE kpi_id='%s'", match[1]) } else { sql = fmt.Sprintf("SELECT en_title FROM kpi_title WHERE kpi_id='%s'", match[1]) } m, err := db.RawDB("", sql, nil) if err != nil { log.Warn("Failed to QueryRow:", err) continue } if len(m) > 0 { if i18n == "zh" { alias = fmt.Sprintf("%v", m[0]["cn_title"]) } else { alias = fmt.Sprintf("%v", m[0]["en_title"]) } } title.ExprAlias = regexp.MustCompile(match[1]).ReplaceAllString(title.ExprAlias, alias) } } } func (k *KpiCTitle) Total(c *gin.Context) { var conditions []string var params []any // construct condition to get if neType := c.Query("neType"); neType != "" { conditions = append(conditions, "ne_type = ?") params = append(params, strings.ToUpper(neType)) } if status := c.Query("status"); status != "" { conditions = append(conditions, "status = ?") params = append(params, status) } else { conditions = append(conditions, "status != '2'") } whereSql := "" if len(conditions) > 0 { whereSql += strings.Join(conditions, " and ") } var total int64 = 0 if err := db.DB("").Table(k.TableName()).Where(whereSql, params...).Count(&total).Error; err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } c.JSON(http.StatusOK, services.TotalResp(total)) } func (k *KpiCTitle) Post(c *gin.Context) { var title KpiCTitle if err := c.ShouldBindJSON(&title); err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } userName := reqctx.LoginUserToUserName(c) title.CreatedBy = &userName tx := db.DB("").Model(&KpiCTitle{}) result := tx.Where("ne_type=? and (kpi_id=? or title=?) and status!='2'", title.NeType, title.KpiID, title.Title).First(&title) if result.RowsAffected > 0 { c.JSON(http.StatusOK, services.ErrResp("custom indicator already exist")) return } // Regexp match like AMF.C.01 // kpiIDRegexp := "^" + *title.NeType + "\\.C\\.[0-9]{2}$" // ret := db.DB("").Table("kpi_c_title"). // Where("ne_type=? and kpi_id REGEXP ? ORDER BY kpi_id DESC LIMIT 1", title.NeType, kpiIDRegexp).Scan(&res) // if err := ret.Error; err != nil { // c.JSON(http.StatusOK, services.ErrResp(err.Error())) // return // } titles := []KpiCTitle{} ret := db.DB("").Model(&KpiCTitle{}) ret = ret.Select("kpi_id").Where("ne_type=?", title.NeType).Find(&titles) newKpiID := *title.NeType + ".C" + ".01" if ret.RowsAffected != 0 { suffixInt := 1 prefixStr := fmt.Sprintf("%s.C.", *title.NeType) sort.SliceStable(titles, func(i, j int) bool { vi := *titles[i].KpiID vj := *titles[j].KpiID if strings.HasPrefix(vi, prefixStr) && strings.HasPrefix(vj, prefixStr) { vvi := strings.Replace(vi, prefixStr, "", 1) vvii, err := strconv.Atoi(vvi) if err != nil { return false } vvj := strings.Replace(vj, prefixStr, "", 1) vvjj, err := strconv.Atoi(vvj) if err != nil { return false } return vvii > vvjj // desc } return false }) maxKpiID := *titles[0].KpiID prefix := maxKpiID[:len(maxKpiID)-2] suffix := maxKpiID[len(maxKpiID)-2:] suffixInt, err := strconv.Atoi(suffix) if err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } if suffixInt >= MAX_KPI_C_ID { err := fmt.Errorf("exceed the max customized KPI ID") c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } suffixInt++ newSuffix := fmt.Sprintf("%02d", suffixInt) newKpiID = prefix + newSuffix } title.KpiID = &newKpiID txx := db.DB("").Model(&KpiCTitle{}) if err := txx.Create(&title).Error; err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } kpiCReportTable := "kpi_c_report_" + strings.ToLower(*title.NeType) if !db.DB("").Migrator().HasTable(kpiCReportTable) { // clone table "kpi_c_report" to "kpi_c_report_{neType}" sql := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s AS SELECT * FROM %s WHERE 1=0", kpiCReportTable, "kpi_c_report") if _, err := db.ExecDB("", sql, nil); err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } sql = fmt.Sprintf("ALTER TABLE %s MODIFY COLUMN `id` int(11) NOT NULL AUTO_INCREMENT FIRST,ADD PRIMARY KEY IF NOT EXISTS (`id`)", kpiCReportTable) if _, err := db.ExecDB("", sql, nil); err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } sql = fmt.Sprintf("ALTER TABLE %s ADD INDEX IF NOT EXISTS `idx_timestamp`(`created_at`) USING BTREE, ADD INDEX IF NOT EXISTS `idx_uid_datetime`(`rm_uid`, `date`, `start_time`) USING BTREE", kpiCReportTable) if _, err := db.ExecDB("", sql, nil); err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } } c.JSON(http.StatusCreated, services.DataResp(title)) } func (k *KpiCTitle) Put(c *gin.Context) { var title KpiCTitle id := c.Param("id") if err := db.DB("").First(&title, id).Error; err != nil { c.JSON(http.StatusOK, services.ErrResp("custom indicator not found")) return } if err := c.ShouldBindJSON(&title); err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } title.UpdatedAt = time.Now().UnixMilli() db.DB("").Save(&title) c.JSON(http.StatusOK, services.DataResp(title)) } func (k *KpiCTitle) Delete(c *gin.Context) { id := c.Param("id") if err := db.DB("").Table(k.TableName()).Where("id=?", id).Update("status", "2").Error; err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } c.JSON(http.StatusNoContent, nil) // 204 No Content } func GetActiveKPICList(neType string) []KpiCTitle { k := new([]KpiCTitle) err := db.DB("").Where("`ne_type` = ? and `status` = '1'", neType).Find(&k).Error if err != nil { return nil } return *k }