Browse Source

Merge remote-tracking branch 'origin/master' into chart/13.8

# Conflicts:
#	controllers/base_from_calculate.go
#	models/edb_data_table.go
#	utils/constants.go
Roc 1 year ago
parent
commit
0634b0c486

+ 9 - 0
controllers/base_from_calculate.go

@@ -1584,6 +1584,15 @@ func (this *CalculateController) Refresh() {
 			errMsg = "RefreshAllCalculateKszs Err:" + err.Error()
 			break
 		}
+	case utils.DATA_SOURCE_STOCK_PLANT: //存量装置
+		//startDate = edbInfo.StartDate
+		endDate = time.Now().Format(utils.FormatDate)
+		req.StartDate = `` // 开始日期也给过滤吧,万一研究员补充了之前的数据呢,还是过滤掉吧
+		err = models.RefreshEdbDataFromStockPlant(req.EdbInfoId, req.EdbCode, req.StartDate)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			errMsg = "RefreshEdbDataFromStockPlant Err:" + err.Error()
+			break
+		}
 	case utils.DATA_SOURCE_CALCULATE_CORRELATION:
 		err, errMsg = models.RefreshAllCalculateCorrelation(edbInfo)
 	default:

+ 138 - 0
controllers/base_from_stock_plant.go

@@ -0,0 +1,138 @@
+package controllers
+
+import (
+	"encoding/json"
+	"hongze/hongze_edb_lib/logic"
+	"hongze/hongze_edb_lib/models"
+	"hongze/hongze_edb_lib/models/supply_analysis"
+	"hongze/hongze_edb_lib/utils"
+	"strconv"
+	"time"
+)
+
+// StockPlantController 存量装置
+type StockPlantController struct {
+	BaseAuthController
+}
+
+// Calculate
+// @Title 计算减产数
+// @Description 计算减产数
+// @Success 200 {object} supply_analysis.CalculateVarietyReq
+// @router /calculate [post]
+func (this *StockPlantController) Calculate() {
+	br := new(models.BaseResponse).Init()
+	var cacheKey string
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req supply_analysis.CalculateVarietyReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.VarietyId <= 0 {
+		br.Msg = "请选择品种!"
+		br.ErrMsg = "请选择品种"
+		return
+	}
+
+	//cacheKey = utils.CACHE_STOCK_PLANT_CALCULATE + strconv.Itoa(req.VarietyId)
+	//if utils.Rc.IsExist(cacheKey) {
+	//	br.Ret = 501
+	//	br.Success = true
+	//	br.Msg = "系统处理中,请稍后重试"
+	//	return
+	//}
+
+	utils.Rc.SetNX(cacheKey, 1, 1*time.Minute)
+	defer func() {
+		utils.Rc.Delete(cacheKey)
+	}()
+
+	err = supply_analysis.Calculate(req.VarietyId, req.AdminId, req.AdminName)
+	if err != nil {
+		br.Msg = "获取指标信息失败!"
+		br.ErrMsg = "获取指标信息失败 AddEdbDataFromManual,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// @Title 刷新手工指标接口
+// @Description 刷新手工指标接口
+// @Success 200 {object} models.RefreshEdbInfoReq
+// @router /refresh [post]
+func (this *StockPlantController) Refresh() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	source := utils.DATA_SOURCE_STOCK_PLANT
+	var req models.RefreshEdbInfoReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.EdbCode == "" {
+		br.Msg = "请输入指标编码!"
+		br.ErrMsg = "请输入指标编码,指标编码为空"
+		return
+	}
+	if req.EdbInfoId <= 0 {
+		br.Msg = "请输入指标ID!"
+		br.ErrMsg = "请输入指标ID"
+		return
+	}
+
+	cacheKey := utils.CACHE_EDB_DATA_REFRESH + strconv.Itoa(source) + "_" + req.EdbCode
+	if utils.Rc.IsExist(cacheKey) {
+		br.Ret = 501
+		br.Success = true
+		br.Msg = "系统处理中,请稍后重试"
+		return
+	}
+
+	// 设置缓存
+	utils.Rc.SetNX(cacheKey, 1, 1*time.Minute)
+	defer func() {
+		utils.Rc.Delete(cacheKey)
+	}()
+	// 获取指标详情
+	edbInfo, err := models.GetEdbInfoByEdbCode(source, req.EdbCode)
+	if err != nil {
+		br.Msg = "指标不存在!"
+		br.ErrMsg = "指标不存在"
+		return
+	}
+
+	req.StartDate = `` // 开始日期也给过滤吧,万一研究员补充了之前的数据呢,还是过滤掉吧
+	err = models.RefreshEdbDataFromStockPlant(req.EdbInfoId, req.EdbCode, req.StartDate)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "刷新指标信息失败!"
+		br.ErrMsg = "刷新指标信息失败 RefreshEdbDataFromManual,Err:" + err.Error()
+		return
+	}
+	// 更新指标最大最小值
+	err, errMsg := models.UnifiedModifyEdbInfoMaxAndMinInfo(edbInfo)
+	if err != nil {
+		br.Msg = errMsg
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	// 更新ES
+	go logic.UpdateEs(edbInfo.EdbInfoId)
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}

+ 21 - 5
controllers/base_from_wind.go

@@ -51,14 +51,30 @@ func (this *WindController) Add() {
 			endDate = time.Now().Format(utils.FormatDate)
 		}
 
-		windUrl, err := GetServerUrl(req.EdbCode)
-		if err != nil {
-			br.Msg = "获取使用的wind地址失败!"
-			br.ErrMsg = "获取使用的wind地址失败,err:" + err.Error()
+		windUrl := ``
+		// 先配置中获取,如果有指定配置的话,那么取配置中的数据
+		tmpConfig, err := models.GetConfigDetailByCode("wind_data_url")
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "获取配置的wind地址失败!"
+			br.ErrMsg = "获取配置的wind地址失败,err:" + err.Error()
+			return
+		}
+		if tmpConfig != nil {
+			windUrl = tmpConfig.ConfigValue
+		} else {
+			windUrl, err = GetServerUrl(req.EdbCode)
+			if err != nil {
+				br.Msg = "获取使用的wind地址失败!"
+				br.ErrMsg = "获取使用的wind地址失败,err:" + err.Error()
+				return
+			}
+		}
+		if windUrl == `` {
+			br.Msg = "没有配置wind地址!"
+			br.ErrMsg = "没有配置wind地址"
 			return
 		}
 
-		windUrl = utils.Hz_Wind_Data_Url_LIST[0].Url
 		//windUrl = utils.Hz_Wind_Data_Url_LIST[1].Url
 		dataItem, errCode, err := services.GetEdbDataFromWindUrl(windUrl, req.EdbCode, utils.BASE_START_DATE, endDate)
 		//dataItem, errCode, err := services.GetEdbDataFromWind(req.EdbCode, utils.BASE_START_DATE, endDate)

+ 155 - 16
models/base_from_adjust.go

@@ -1,6 +1,7 @@
 package models
 
 import (
+	"errors"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"hongze/hongze_edb_lib/services/alarm_msg"
@@ -107,6 +108,23 @@ func SaveAdjustEdb(req SaveAdjustEdbReq) (edbInfo *EdbInfo, err error, errMsg st
 				return
 			}
 		}
+		//相关配置
+		{
+			var fromEdbEndDate time.Time
+			if fromEdbInfo.EndDate != `0000-00-00` {
+				fromEdbEndDate, _ = time.Parse(utils.FormatDate, fromEdbInfo.EndDate)
+			}
+			edbAdjustConf := &EdbAdjustConf{
+				EdbInfoId:     edbInfo.EdbInfoId,
+				SourceEndDate: fromEdbEndDate,
+				ModifyTime:    time.Now(),
+				CreateTime:    time.Now(),
+			}
+			_, err = to.Insert(edbAdjustConf)
+			if err != nil {
+				return
+			}
+		}
 	} else {
 		edbInfo, err = GetEdbInfoById(req.EdbInfoId)
 		if err != nil {
@@ -136,6 +154,45 @@ func SaveAdjustEdb(req SaveAdjustEdbReq) (edbInfo *EdbInfo, err error, errMsg st
 		if err != nil {
 			return
 		}
+
+		//相关配置
+		{
+			// 获取来源指标
+			calculateMapping, tmpErr := GetEdbInfoCalculateMappingDetail(edbInfo.EdbInfoId)
+			if tmpErr != nil {
+				errMsg = `关联指标获取异常`
+				err = tmpErr
+				return
+			}
+			fromEdbInfo, tmpErr := GetEdbInfoById(calculateMapping.FromEdbInfoId)
+			if tmpErr != nil {
+				errMsg = `来源指标不存在`
+				err = tmpErr
+				return
+			}
+			var fromEdbEndDate time.Time
+			if fromEdbInfo.EndDate != `0000-00-00` {
+				fromEdbEndDate, _ = time.Parse(utils.FormatDate, fromEdbInfo.EndDate)
+			}
+
+			// 获取之前的配置
+			var edbAdjustConf *EdbAdjustConf
+			sql := ` SELECT * FROM edb_adjust_conf WHERE edb_info_id=? `
+			err = o.Raw(sql, edbInfo.EdbInfoId).QueryRow(&edbAdjustConf)
+			if err != nil {
+				errMsg = "获取指标配置失败"
+				return
+			}
+
+			// 修改配置的最晚日期
+			edbAdjustConf.SourceEndDate = fromEdbEndDate
+			edbAdjustConf.ModifyTime = time.Now()
+			_, err = to.Update(edbAdjustConf, "SourceEndDate", "ModifyTime")
+			if err != nil {
+				errMsg = "更新指标配置失败"
+				return
+			}
+		}
 	}
 	dataList := req.DataList
 
@@ -200,13 +257,15 @@ func RefreshAllAdjustEdb(edbInfo *EdbInfo, fromEdbInfo *EdbInfo) (err error) {
 		}
 	}()
 
-	// 获取当前指标的最晚的日期
+	// 当前数据表名
 	dataTableName := GetEdbDataTableName(edbInfo.Source)
-	var maxDate string
-	sql := `SELECT max(data_time) data_time FROM %s WHERE edb_info_id=? `
-	sql = fmt.Sprintf(sql, dataTableName)
-	err = to.Raw(sql, edbInfo.EdbInfoId).QueryRow(&maxDate)
+
+	// 获取之前的配置
+	var edbAdjustConf *EdbAdjustConf
+	sql := ` SELECT * FROM edb_adjust_conf WHERE edb_info_id=? `
+	err = o.Raw(sql, edbInfo.EdbInfoId).QueryRow(&edbAdjustConf)
 	if err != nil {
+		err = errors.New("获取指标配置失败")
 		return
 	}
 
@@ -214,31 +273,60 @@ func RefreshAllAdjustEdb(edbInfo *EdbInfo, fromEdbInfo *EdbInfo) (err error) {
 	var condition string
 	var pars []interface{}
 	condition += " AND edb_info_id=? AND data_time > ? "
-	pars = append(pars, fromEdbInfo.EdbInfoId, maxDate)
-
+	pars = append(pars, fromEdbInfo.EdbInfoId, edbAdjustConf.SourceEndDate)
 	dataList, err := GetEdbDataListAllByTo(to, condition, pars, fromEdbInfo.Source, 1)
 	if err != nil {
 		return err
 	}
 
-	var isAdd bool
-	addSql := ` INSERT INTO ` + dataTableName + `(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
-	for _, item := range dataList {
-		//格式化时间
-		currentDate, tmpErr := time.ParseInLocation(utils.FormatDate, item.DataTime, time.Local)
+	// 已经入库的日期数据
+	existDataMap := make(map[string]float64)
+	{
+		var tmpCondition string
+		var tmpPars []interface{}
+		condition += " AND edb_info_id=? AND data_time > ? "
+		pars = append(pars, fromEdbInfo.EdbInfoId, edbAdjustConf.SourceEndDate)
+		existDataList, tmpErr := GetEdbDataListAllByTo(to, tmpCondition, tmpPars, edbInfo.Source, 1)
 		if tmpErr != nil {
 			err = tmpErr
 			return
 		}
-		timestamp := currentDate.UnixNano() / 1e6
-		timestampStr := fmt.Sprintf("%d", timestamp)
+		for _, v := range existDataList {
+			existDataMap[v.DataTime] = v.Value
+		}
+	}
 
+	var isAdd bool
+	addSql := ` INSERT INTO ` + dataTableName + `(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
+	for _, item := range dataList {
+		currDay := item.DataTime
 		//值
 		val := item.Value
 		saveVal := utils.SubFloatToString(val, 20)
-		addSql += GetAddSql(fmt.Sprint(edbInfo.EdbInfoId), edbInfo.EdbCode, item.DataTime, timestampStr, saveVal)
+		if existVal, ok := existDataMap[currDay]; !ok {
+			//格式化时间
+			currentDate, tmpErr := time.Parse(utils.FormatDate, item.DataTime)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			timestamp := currentDate.UnixNano() / 1e6
+			timestampStr := fmt.Sprintf("%d", timestamp)
+
+			addSql += GetAddSql(fmt.Sprint(edbInfo.EdbInfoId), edbInfo.EdbCode, item.DataTime, timestampStr, saveVal)
+
+			isAdd = true
+		} else {
+			if existVal != item.Value {
+				sql = ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
+				sql = fmt.Sprintf(sql, dataTableName)
+				_, err = to.Raw(sql, saveVal, edbInfo.EdbInfoId, currDay).Exec()
+				if err != nil {
+					return err
+				}
+			}
+		}
 
-		isAdd = true
 	}
 	if isAdd {
 		addSql = strings.TrimRight(addSql, ",")
@@ -248,6 +336,17 @@ func RefreshAllAdjustEdb(edbInfo *EdbInfo, fromEdbInfo *EdbInfo) (err error) {
 		}
 	}
 
+	// 变更数据调整配置表的实际结束日期
+	{
+		var fromEdbEndDate time.Time
+		if fromEdbInfo.EndDate != `0000-00-00` {
+			fromEdbEndDate, _ = time.Parse(utils.FormatDate, fromEdbInfo.EndDate)
+		}
+		edbAdjustConf.SourceEndDate = fromEdbEndDate
+		edbAdjustConf.ModifyTime = time.Now()
+		_, err = to.Update(edbAdjustConf, "SourceEndDate", "ModifyTime")
+	}
+
 	return
 }
 
@@ -269,3 +368,43 @@ type SaveAdjustEdbDataReq struct {
 	Date  string  `description:"数据日期"`
 	Value float64 `description:"数据值"`
 }
+
+// FixData 修复数据
+func FixData() {
+	var list []*EdbInfo
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM edb_info WHERE source=? `
+	_, err := o.Raw(sql, 40).QueryRows(&list)
+	for _, edbInfo := range list {
+		// 获取来源指标
+		calculateMapping, tmpErr := GetEdbInfoCalculateMappingDetail(edbInfo.EdbInfoId)
+		if tmpErr != nil {
+			fmt.Println(edbInfo.EdbInfoId, "关联指标获取异常;err:", tmpErr)
+			continue
+		}
+		fromEdbInfo, tmpErr := GetEdbInfoById(calculateMapping.FromEdbInfoId)
+		if tmpErr != nil {
+			fmt.Println(edbInfo.EdbInfoId, "来源指标不存在;err:", tmpErr)
+			continue
+		}
+		var fromEdbEndDate time.Time
+		if fromEdbInfo.EndDate != `0000-00-00` {
+			fromEdbEndDate, _ = time.Parse(utils.FormatDate, fromEdbInfo.EndDate)
+		}
+
+		// 获取之前的配置
+		edbAdjustConf := &EdbAdjustConf{
+			EdbInfoId:     edbInfo.EdbInfoId,
+			SourceEndDate: fromEdbEndDate,
+			ModifyTime:    time.Now(),
+			CreateTime:    time.Now(),
+		}
+		_, err = o.Insert(edbAdjustConf)
+		if err != nil {
+			fmt.Println(edbInfo.EdbInfoId, "添加失败;err:", tmpErr)
+			continue
+		}
+
+	}
+	fmt.Println("end")
+}

+ 16 - 3
models/base_from_manual.go

@@ -3,6 +3,7 @@ package models
 import (
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
+	"github.com/shopspring/decimal"
 	"hongze/hongze_edb_lib/utils"
 	"strconv"
 	"strings"
@@ -29,7 +30,7 @@ func GetEdbdataManualByCondition(condition string, pars []interface{}) (item []*
 	return
 }
 
-// 新增弘则手工指标数据
+// AddEdbDataFromManual 新增弘则手工指标数据
 func AddEdbDataFromManual(edbCode string) (err error) {
 	o := orm.NewOrm()
 
@@ -54,6 +55,13 @@ func AddEdbDataFromManual(edbCode string) (err error) {
 			item := manualDataList[i]
 			eDate := item.Dt
 			sValue := item.Close
+			tmpDecimal, err := decimal.NewFromString(sValue)
+			if err != nil {
+				return err
+			}
+			sValue = tmpDecimal.Round(4).String()
+
+
 			dataTime, err := time.ParseInLocation(utils.FormatDate, eDate, time.Local)
 			if err != nil {
 				return err
@@ -74,7 +82,7 @@ func AddEdbDataFromManual(edbCode string) (err error) {
 	return
 }
 
-// 刷新手工指标数据
+// RefreshEdbDataFromManual 刷新手工指标数据
 func RefreshEdbDataFromManual(edbInfoId int, edbCode, startDate string) (err error) {
 	source := utils.DATA_SOURCE_MANUAL
 	o := orm.NewOrm()
@@ -139,7 +147,7 @@ func RefreshEdbDataFromManual(edbInfoId int, edbCode, startDate string) (err err
 		existMap[v.DataTime] = v
 	}
 
-	addSql := ` INSERT INTO edb_data_manual(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
+	addSql := ` INSERT INTO edb_data_manual (edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
 	var isAdd bool
 	manualMap := make(map[string]*ManualEdbdata)
 	//fmt.Println("manualDataList:", len(manualDataList))
@@ -147,6 +155,11 @@ func RefreshEdbDataFromManual(edbInfoId int, edbCode, startDate string) (err err
 		item := v
 		eDate := item.Dt
 		sValue := item.Close
+		tmpDecimal, err := decimal.NewFromString(sValue)
+		if err != nil {
+			return err
+		}
+		sValue = tmpDecimal.Round(4).String()
 
 		dataTime, err := time.ParseInLocation(utils.FormatDate, eDate, time.Local)
 		if err != nil {

+ 129 - 0
models/base_from_stock_plant.go

@@ -0,0 +1,129 @@
+package models
+
+import (
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"hongze/hongze_edb_lib/models/supply_analysis"
+	"hongze/hongze_edb_lib/utils"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// StockPlantEdbdata 存量装置数据
+type StockPlantEdbdata struct {
+	VarietyEdbId string    `orm:"column(variety_edb_id);pk" description:"指标编码"`
+	DataTime     string    `orm:"column(data_time)" description:"日期"`
+	Value        string    `orm:"column(value)" description:"值"`
+	ModifyTime   time.Time `orm:"column(modify_time)" description:"修改时间"`
+}
+
+func GetStockPlantEdbDataByCondition(condition string, pars []interface{}) (item []*StockPlantEdbdata, err error) {
+	sql := ` SELECT  * FROM base_from_stock_plant_data WHERE 1=1  `
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` ORDER BY data_time DESC `
+	o := orm.NewOrm()
+	_, err = o.Raw(sql, pars).QueryRows(&item)
+	return
+}
+
+// RefreshEdbDataFromStockPlant 刷新存量装置数据
+func RefreshEdbDataFromStockPlant(edbInfoId int, edbCode, startDate string) (err error) {
+	source := utils.DATA_SOURCE_STOCK_PLANT
+	o := orm.NewOrm()
+	if err != nil {
+		return
+	}
+	edbInfoIdStr := strconv.Itoa(edbInfoId)
+	//计算数据
+	var condition string
+	var pars []interface{}
+
+	// 获取供应分析的指标信息
+	varietyEdbInfo, err := supply_analysis.GetVarietyEdbInfoByEdbInfoId(edbInfoId)
+	if err != nil {
+		return
+	}
+
+	// 获取基础库的指标数据
+	condition += " AND variety_edb_id=? "
+	pars = append(pars, varietyEdbInfo.VarietyEdbId)
+
+	if startDate != "" {
+		condition += " AND data_time >=? "
+		pars = append(pars, startDate)
+	} else {
+		condition += " AND data_time != ? "
+		pars = append(pars, `0000-00-00`)
+	}
+
+	baseDataList, err := GetStockPlantEdbDataByCondition(condition, pars)
+
+	var existCondition string
+	var existPars []interface{}
+
+	existCondition += " AND edb_info_id=? "
+	existPars = append(existPars, edbInfoId)
+	if startDate != "" {
+		existCondition += " AND data_time>=? "
+		existPars = append(existPars, startDate)
+	}
+
+	existList, err := GetEdbDataByCondition(source, existCondition, existPars)
+	if err != nil {
+		return err
+	}
+	existMap := make(map[string]*EdbInfoSearchData)
+	for _, v := range existList {
+		existMap[v.DataTime] = v
+	}
+
+	addSql := ` INSERT INTO edb_data_stock_plant (edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
+	var isAdd bool
+	manualMap := make(map[string]*StockPlantEdbdata)
+	for _, v := range baseDataList {
+		item := v
+		//fmt.Println("Item:", item.Dt, item.Close, item.TradeCode, item.ModifyTime)
+		if findItem, ok := existMap[v.DataTime]; !ok {
+			eDate := item.DataTime
+			sValue := item.Value
+
+			dataTime, err := time.Parse(utils.FormatDate, eDate)
+			if err != nil {
+				return err
+			}
+			timestamp := dataTime.UnixNano() / 1e6
+			timeStr := fmt.Sprintf("%d", timestamp)
+
+			addSql += GetAddSql(edbInfoIdStr, edbCode, eDate, timeStr, sValue)
+			isAdd = true
+		} else {
+			if findItem != nil && utils.SubFloatToString(findItem.Value, 30) != item.Value {
+				err = ModifyEdbDataById(source, findItem.EdbDataId, item.Value)
+				if err != nil {
+					return err
+				}
+			}
+		}
+		manualMap[v.DataTime] = v
+	}
+	// 删除不存在的日期数据
+	for _, v := range existList {
+		if _, ok := manualMap[v.DataTime]; !ok {
+			go DeleteEdbDataById(source, v.EdbDataId)
+		}
+	}
+
+	// 将数据入库
+	if isAdd {
+		addSql = strings.TrimRight(addSql, ",")
+		_, err = o.Raw(addSql).Exec()
+		if err != nil {
+			fmt.Println("RefreshAllEdbDataByStockPlant add Err", err.Error())
+			return
+		}
+	}
+	return
+}

+ 16 - 0
models/db.go

@@ -4,6 +4,7 @@ import (
 	"github.com/beego/beego/v2/client/orm"
 	_ "github.com/go-sql-driver/mysql"
 	"hongze/hongze_edb_lib/models/future_good"
+	"hongze/hongze_edb_lib/models/supply_analysis"
 	"hongze/hongze_edb_lib/utils"
 	"time"
 )
@@ -51,10 +52,14 @@ func init() {
 		new(EdbDataPredictCalculateNhcc),
 		new(EdbDataPredictCalculateZjpj),
 		new(EdbDataInsertConfig),
+		new(EdbAdjustConf), // 数据调整的配置
 	)
 
 	// 注册期货数据 数据表
 	initFutureGood()
+
+	// 供应分析 数据表
+	initSupplyAnalysis()
 }
 
 // initFutureGood 注册期货数据 数据表
@@ -65,3 +70,14 @@ func initFutureGood() {
 		new(future_good.FutureGoodEdbData), //期货指标数据表
 	)
 }
+
+// initSupplyAnalysis 供应分析
+func initSupplyAnalysis() {
+	orm.RegisterModel(
+		new(supply_analysis.Variety),
+		new(supply_analysis.VarietyAdminPermission),
+		new(supply_analysis.VarietyEdbInfo),
+		new(supply_analysis.VarietyPlant),
+		new(supply_analysis.BaseFromStockPlantData),
+	)
+}

+ 13 - 0
models/edb_adjust_conf.go

@@ -0,0 +1,13 @@
+package models
+
+import (
+	"time"
+)
+
+// EdbAdjustConf 计算指标于基础指标,关系表
+type EdbAdjustConf struct {
+	EdbInfoId     int       `orm:"column(edb_info_id);pk" description:"计算指标id"`
+	SourceEndDate time.Time `description:"来源指标的实际数据日期"`
+	ModifyTime    time.Time `description:"修改时间"`
+	CreateTime    time.Time `description:"创建时间"`
+}

+ 23 - 0
models/edb_config.go

@@ -0,0 +1,23 @@
+package models
+
+import "github.com/beego/beego/v2/client/orm"
+
+type EdbConfig struct {
+	ConfigValue string `description:"详情"`
+}
+
+// EdbConfigUpdate 修改配置
+func EdbConfigUpdate(newValue, configCode string) (err error) {
+	o := orm.NewOrm()
+	sql := `UPDATE edb_config SET  config_value=?   WHERE config_code=  ?`
+	_, err = o.Raw(sql, newValue, configCode).Exec()
+	return
+}
+
+// GetConfigDetailByCode 根据配置编码获取配置的值
+func GetConfigDetailByCode(configCode string) (item *EdbConfig, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT config_value FROM edb_config WHERE config_code=? `
+	err = o.Raw(sql, configCode).QueryRow(&item)
+	return
+}

+ 412 - 0
models/supply_analysis/base_from_stock_plant_data.go

@@ -0,0 +1,412 @@
+package supply_analysis
+
+import (
+	"errors"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"github.com/shopspring/decimal"
+	"hongze/hongze_edb_lib/utils"
+	"time"
+)
+
+// BaseFromStockPlantData base_from_stock_plant_data 存量装置的指标的计算数据
+type BaseFromStockPlantData struct {
+	StockPlantDataId int       `orm:"column(stock_plant_data_id);pk"`
+	VarietyEdbId     int       `description:"指标id"`
+	DataTime         time.Time `description:"数据日期"`
+	Value            float64   `description:"数据值"`
+	ModifyTime       time.Time `description:"修改时间"`
+	CreateTime       time.Time `description:"创建时间"`
+	DataTimestamp    int64     `description:"数据日期时间戳"`
+}
+
+// CalculateVarietyReq 重新计算请求
+type CalculateVarietyReq struct {
+	VarietyId int    `description:"品种id"`
+	AdminId   int    `description:"操作人id"`
+	AdminName string `description:"操作人名称"`
+}
+
+func Calculate(varietyId int, sysUserId int, sysUserName string) (err error) {
+	varietyInfo, err := GetVarietyById(varietyId)
+	if err != nil {
+		return
+	}
+
+	// 获取所有的装置
+	plantList, err := GetAllVarietyPlantByVarietyId(varietyId)
+	if err != nil {
+		return
+	}
+
+	// 获取所有的指标
+	varietyEdbInfoList, err := GetAllVarietyEdbInfoByVarietyId(varietyId)
+	if err != nil {
+		return
+	}
+
+	// 维修数据的开始日期和结束日期
+	var startDate, endDate time.Time
+	//所有设备在该日期的减产数
+	maintenanceDataMap := make(map[time.Time][]float64)
+
+	for _, plantInfo := range plantList {
+		// 开始检修日期
+		if startDate.IsZero() || plantInfo.MaintenanceDate.Before(startDate) {
+			startDate = plantInfo.MaintenanceDate
+		}
+		// 结束检修日期
+		if endDate.IsZero() || plantInfo.ResumptionDate.After(endDate) {
+			endDate = plantInfo.ResumptionDate
+		}
+
+		for tmpDate := plantInfo.MaintenanceDate; !tmpDate.After(plantInfo.ResumptionDate); tmpDate = tmpDate.AddDate(0, 0, 1) {
+			dataList, ok := maintenanceDataMap[tmpDate]
+			if !ok {
+				dataList = make([]float64, 0)
+			}
+			dataList = append(dataList, plantInfo.AverageDailyCapacityReduction)
+			maintenanceDataMap[tmpDate] = dataList
+		}
+	}
+
+	// 产生的数据的结束日期
+	var lastDate time.Time
+
+	currDate := time.Now()
+	currHour := currDate.Hour()
+	if currHour < 22 {
+		lastDate, _ = time.ParseInLocation(utils.FormatDate, currDate.Format(utils.FormatDate), time.Local)
+	} else {
+		lastDate, _ = time.ParseInLocation(utils.FormatDate, currDate.AddDate(0, 0, 1).Format(utils.FormatDate), time.Local)
+	}
+	lastDate = lastDate.AddDate(1, 0, 0) //业务需要计算的数据日期往当前日期后面加上一年
+
+	// 计算出数据
+	dataMap := make(map[time.Time]float64)
+	for tmpDate := startDate; !tmpDate.After(lastDate); tmpDate = tmpDate.AddDate(0, 0, 1) {
+		var calculateVal float64
+		tmpDataList, ok := maintenanceDataMap[tmpDate]
+		// 如果没有维修数据,那么退出当前循环,进入下一个循环
+		if !ok {
+			calculateVal = 0
+		} else {
+			for _, tmpVal := range tmpDataList {
+				calculateVal += tmpVal
+			}
+		}
+
+		dataMap[tmpDate] = calculateVal
+	}
+
+	to, err := orm.NewOrm().Begin()
+	if err != nil {
+		return
+	}
+
+	defer func() {
+		if err != nil {
+			fmt.Println("Calculate,Err:" + err.Error())
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	for _, varietyEdbInfo := range varietyEdbInfoList {
+		err = calculateEdb(to, varietyEdbInfo, dataMap, startDate, lastDate)
+		if err != nil {
+			return
+		}
+	}
+
+	// 更新最后分析的人员信息
+	varietyInfo.LastUpdateSysUserId = sysUserId
+	varietyInfo.LastUpdateSysUserRealName = sysUserName
+	varietyInfo.ModifyTime = time.Now()
+	_, err = to.Update(varietyInfo, "LastUpdateSysUserId", "LastUpdateSysUserRealName", "ModifyTime")
+
+	return
+}
+
+func calculateEdb(to orm.TxOrmer, varietyEdbInfo *VarietyEdbInfo, dataMap map[time.Time]float64, startDate, lastDate time.Time) (err error) {
+	sql := `SELECT * FROM base_from_stock_plant_data WHERE variety_edb_id = ? `
+	var list []*BaseFromStockPlantData
+	_, err = to.Raw(sql, varietyEdbInfo.VarietyEdbId).QueryRows(&list)
+	if err != nil {
+		return
+	}
+
+	addList := make([]*BaseFromStockPlantData, 0)
+	deleteIdMap := make(map[int]int, 0)
+
+	existData := make(map[time.Time]*BaseFromStockPlantData)
+	for _, v := range list {
+		existData[v.DataTime] = v
+		deleteIdMap[v.StockPlantDataId] = v.StockPlantDataId
+	}
+
+	tmpDataList := make([]float64, 0) // 每天的值
+	var preSumValDeci decimal.Decimal // 上一期的值
+	endDate := lastDate               // 实际数据最后结束的日期
+	var latestValue float64           // 最新值
+	switch varietyEdbInfo.Source {
+	//1:影响周度产量;2:周度产量变动;3:影响月度产量;4:月度产量变动
+	case 1, 2:
+		// 期间周度数据
+		for tmpDate := startDate; !tmpDate.After(lastDate); tmpDate = tmpDate.AddDate(0, 0, 1) {
+			//tmpData, ok := dataMap[tmpDate]
+			//if !ok {
+			//	continue
+			//}
+			//tmpDataList = append(tmpDataList, tmpData)
+			//
+			//if tmpDate.Weekday() != 0 {
+			//	// 如果不是周日,那么就退出当前循环
+			//	continue
+			//}
+			//
+			//
+			//// 日期期间汇总数据
+			//var sumVal float64
+			//for _, tmpVal := range tmpDataList {
+			//	sumVal += tmpVal
+			//}
+			//sumValDeci := decimal.NewFromFloat(sumVal)
+			//
+			//var currVal float64
+			//if varietyEdbInfo.Source == 2 { // 如果是变动的话,那么是
+			//	currVal, _ = (decimal.NewFromFloat(sumVal).Sub(preSumValDeci)).Round(4).Float64()
+			//} else {
+			//	currVal, _ = sumValDeci.Round(4).Float64()
+			//}
+			//preSumValDeci = sumValDeci       // 赋值给上一个周期的截止值
+
+			currVal, ok := dataMap[tmpDate]
+			if !ok {
+				continue
+			}
+			preSumValDeci = decimal.NewFromFloat(currVal) // 赋值给上一个周期的截止值
+			latestValue = currVal
+
+			tmpDataList = make([]float64, 0) //重置值列表,便于下一个周期计算
+
+			timestamp := tmpDate.UnixNano() / 1e6
+			existItem, ok := existData[tmpDate]
+			if !ok {
+				addList = append(addList, &BaseFromStockPlantData{
+					//StockPlantDataId: 0,
+					VarietyEdbId:  varietyEdbInfo.VarietyEdbId,
+					DataTime:      tmpDate,
+					Value:         currVal,
+					ModifyTime:    time.Now(),
+					CreateTime:    time.Now(),
+					DataTimestamp: timestamp,
+				})
+			} else {
+				if existItem.Value != currVal {
+					existItem.Value = currVal
+					existItem.ModifyTime = time.Now()
+					_, err = to.Update(existItem, "Value", "ModifyTime")
+					if err != nil {
+						return
+					}
+				}
+
+				delete(deleteIdMap, existItem.StockPlantDataId)
+			}
+		}
+
+		// 最后一周,不满一周时的计算
+		//lastDateWeek := lastDate.Weekday()
+		//if lastDateWeek != 0 {
+		//	// 如果最后一天不是周日,那么需要把日期调整到周日
+		//	subDay := 7 - lastDateWeek
+		//	tmpDate := lastDate.AddDate(0, 0, int(subDay))
+		//	endDate = tmpDate //数据实际结束的日期
+		//
+		//	existItem, ok := existData[tmpDate]
+		//
+		//	timestamp := tmpDate.UnixNano() / 1e6
+		//	// 日期期间汇总数据
+		//	var sumVal float64
+		//	for _, tmpVal := range tmpDataList {
+		//		sumVal += tmpVal
+		//	}
+		//	sumValDeci := decimal.NewFromFloat(sumVal)
+		//
+		//	var currVal float64
+		//	if varietyEdbInfo.Source == 2 { // 如果是变动的话,那么是
+		//		currVal, _ = (decimal.NewFromFloat(sumVal).Sub(preSumValDeci)).Round(4).Float64()
+		//	} else {
+		//		currVal, _ = sumValDeci.Round(4).Float64()
+		//	}
+		//	latestValue = currVal
+		//
+		//	if !ok {
+		//		addList = append(addList, &BaseFromStockPlantData{
+		//			//StockPlantDataId: 0,
+		//			VarietyEdbId:  varietyEdbInfo.VarietyEdbId,
+		//			DataTime:      tmpDate,
+		//			Value:         currVal,
+		//			ModifyTime:    time.Now(),
+		//			CreateTime:    time.Now(),
+		//			DataTimestamp: timestamp,
+		//		})
+		//	} else {
+		//		if existItem.Value != currVal {
+		//			existItem.Value = currVal
+		//			existItem.ModifyTime = time.Now()
+		//			_, err = to.Update(existItem, "Value", "ModifyTime")
+		//			if err != nil {
+		//				return
+		//			}
+		//		}
+		//
+		//		delete(deleteIdMap, existItem.StockPlantDataId)
+		//	}
+		//}
+
+	case 3, 4:
+		// 期间月度数据
+		for tmpDate := startDate; !tmpDate.After(lastDate); tmpDate = tmpDate.AddDate(0, 0, 1) {
+			tmpData, ok := dataMap[tmpDate]
+			if !ok {
+				continue
+			}
+			tmpDataList = append(tmpDataList, tmpData)
+
+			if tmpDate.AddDate(0, 0, 1).Day() != 1 {
+				// 如果不是每个月的最后一日,那么就退出当前循环
+				continue
+			}
+
+			timestamp := tmpDate.UnixNano() / 1e6
+
+			// 日期期间汇总数据
+			var sumVal float64
+			for _, tmpVal := range tmpDataList {
+				sumVal += tmpVal
+			}
+			sumValDeci := decimal.NewFromFloat(sumVal)
+
+			var currVal float64
+			if varietyEdbInfo.Source == 2 { // 如果是变动的话,那么是
+				currVal, _ = (decimal.NewFromFloat(sumVal).Sub(preSumValDeci)).Round(4).Float64()
+			} else {
+				currVal, _ = sumValDeci.Round(4).Float64()
+			}
+			latestValue = currVal
+
+			preSumValDeci = sumValDeci       // 赋值给上一个周期的截止值
+			tmpDataList = make([]float64, 0) //重置值列表,便于下一个周期计算
+
+			existItem, ok := existData[tmpDate]
+			if !ok {
+				addList = append(addList, &BaseFromStockPlantData{
+					//StockPlantDataId: 0,
+					VarietyEdbId:  varietyEdbInfo.VarietyEdbId,
+					DataTime:      tmpDate,
+					Value:         currVal,
+					ModifyTime:    time.Now(),
+					CreateTime:    time.Now(),
+					DataTimestamp: timestamp,
+				})
+			} else {
+				if existItem.Value != currVal {
+					existItem.Value = currVal
+					existItem.ModifyTime = time.Now()
+					_, err = to.Update(existItem, "Value", "ModifyTime")
+					if err != nil {
+						return
+					}
+				}
+
+				delete(deleteIdMap, existItem.StockPlantDataId)
+			}
+		}
+
+		// 最后一月,不满一月时的计算
+		currMonthEndDay := time.Date(lastDate.Year(), lastDate.Month(), 1, 0, 0, 0, 0, time.Local).AddDate(0, 1, -1)
+		if !lastDate.Equal(currMonthEndDay) {
+			// 如果最后一天不是当月的最后一天,那么需要把日期调整到当月的最后一天
+			tmpDate := currMonthEndDay
+			endDate = tmpDate //数据实际结束的日期
+
+			existItem, ok := existData[tmpDate]
+
+			timestamp := tmpDate.UnixNano() / 1e6
+			// 日期期间汇总数据
+			var sumVal float64
+			for _, tmpVal := range tmpDataList {
+				sumVal += tmpVal
+			}
+			sumValDeci := decimal.NewFromFloat(sumVal)
+
+			var currVal float64
+			if varietyEdbInfo.Source == 2 { // 如果是变动的话,那么是
+				currVal, _ = (decimal.NewFromFloat(sumVal).Sub(preSumValDeci)).Round(4).Float64()
+			} else {
+				currVal, _ = sumValDeci.Round(4).Float64()
+			}
+			latestValue = currVal
+
+			if !ok {
+				addList = append(addList, &BaseFromStockPlantData{
+					//StockPlantDataId: 0,
+					VarietyEdbId:  varietyEdbInfo.VarietyEdbId,
+					DataTime:      tmpDate,
+					Value:         currVal,
+					ModifyTime:    time.Now(),
+					CreateTime:    time.Now(),
+					DataTimestamp: timestamp,
+				})
+			} else {
+				if existItem.Value != currVal {
+					existItem.Value = currVal
+					existItem.ModifyTime = time.Now()
+					_, err = to.Update(existItem, "Value", "ModifyTime")
+					if err != nil {
+						return
+					}
+				}
+
+				delete(deleteIdMap, existItem.StockPlantDataId)
+			}
+		}
+	default:
+		err = errors.New("错误的指标类型")
+		return
+	}
+
+	// 需要添加的指标数据
+	lenAddList := len(addList)
+	if lenAddList > 0 {
+		_, err = to.InsertMulti(lenAddList, addList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 删除不存在的数据
+	lenDeleteIdMap := len(deleteIdMap)
+	if len(deleteIdMap) > 0 {
+		deleteIdList := make([]int, 0)
+		for _, v := range deleteIdMap {
+			deleteIdList = append(deleteIdList, v)
+		}
+		sql = ` DELETE FROM base_from_stock_plant_data WHERE stock_plant_data_id in (` + utils.GetOrmInReplace(lenDeleteIdMap) + `) `
+		_, err = to.Raw(sql, deleteIdList).Exec()
+		if err != nil {
+			return
+		}
+	}
+
+	varietyEdbInfo.StartDate = startDate
+	varietyEdbInfo.EndDate = endDate
+	varietyEdbInfo.LatestValue = latestValue
+	varietyEdbInfo.ModifyTime = time.Now()
+	_, err = to.Update(varietyEdbInfo, "StartDate", "EndDate", "LatestValue", "ModifyTime")
+
+	return
+}

+ 214 - 0
models/supply_analysis/variety.go

@@ -0,0 +1,214 @@
+package supply_analysis
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// Variety variety 品种表
+type Variety struct {
+	VarietyId                 int       `orm:"column(variety_id);pk"`
+	VarietyName               string    `description:"品种名称"`
+	LastUpdateSysUserId       int       `description:"最后更新人id"`
+	LastUpdateSysUserRealName string    `description:"最后更新人名称"`
+	SysUserId                 int       `description:"创建人id"`
+	SysUserRealName           string    `description:"创建人姓名"`
+	ModifyTime                time.Time `description:"修改时间"`
+	CreateTime                time.Time `description:"创建时间"`
+}
+
+// GetVarietyById 根据品种id获取品种详情
+func GetVarietyById(id int) (item *Variety, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM variety WHERE variety_id = ?`
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+// GetVarietyByName 根据品种名称获取品种详情
+func GetVarietyByName(name string) (item *Variety, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM variety WHERE variety_name = ?`
+	err = o.Raw(sql, name).QueryRow(&item)
+	return
+}
+
+// AddVariety 添加品种
+func AddVariety(item *Variety) (lastId int64, err error) {
+	o := orm.NewOrm()
+	lastId, err = o.Insert(item)
+	return
+}
+
+// CreateVariety 添加品种
+func CreateVariety(item *Variety, adminIdList []int) (err error) {
+	to, err := orm.NewOrm().Begin()
+	if err != nil {
+		return
+	}
+
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+	lastId, err := to.Insert(item)
+	if err != nil {
+		return
+	}
+
+	item.VarietyId = int(lastId)
+
+	varietyAdminPermissionList := make([]*VarietyAdminPermission, 0)
+	for _, adminId := range adminIdList {
+		varietyAdminPermissionList = append(varietyAdminPermissionList, &VarietyAdminPermission{
+			//Id:              0,
+			VarietyId:  item.VarietyId,
+			SysUserId:  adminId,
+			CreateTime: time.Now(),
+		})
+	}
+	if len(varietyAdminPermissionList) > 0 {
+		_, err = to.InsertMulti(len(varietyAdminPermissionList), varietyAdminPermissionList)
+	}
+
+	return
+}
+
+// EditVariety 编辑品种
+func EditVariety(item *Variety, adminIdList []int) (err error) {
+	to, err := orm.NewOrm().Begin()
+	if err != nil {
+		return
+	}
+
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	_, err = to.Update(item, "VarietyName", "LastUpdateSysUserId", "LastUpdateSysUserRealName", "ModifyTime")
+	if err != nil {
+		return
+	}
+
+	// 删除历史的权限配置
+	sql := `DELETE FROM variety_admin_permission where variety_id = ? `
+	_, err = to.Raw(sql, item.VarietyId).Exec()
+	if err != nil {
+		return
+	}
+
+	// 添加新的权限配置
+	varietyAdminPermissionList := make([]*VarietyAdminPermission, 0)
+	for _, adminId := range adminIdList {
+		varietyAdminPermissionList = append(varietyAdminPermissionList, &VarietyAdminPermission{
+			//Id:              0,
+			VarietyId:  item.VarietyId,
+			SysUserId:  adminId,
+			CreateTime: time.Now(),
+		})
+	}
+	if len(varietyAdminPermissionList) > 0 {
+		_, err = to.InsertMulti(len(varietyAdminPermissionList), varietyAdminPermissionList)
+	}
+
+	return
+}
+
+// VarietyItem 列表页返回的数据结构
+type VarietyItem struct {
+	VarietyId                 int           `orm:"column(variety_id);pk"`
+	VarietyName               string        `description:"品种名称"`
+	LastUpdateSysUserId       int           `description:"最后更新人id"`
+	LastUpdateSysUserRealName string        `description:"最后更新人名称"`
+	PermissionUserId          string        `description:"有操作权限的用户id" json:"-"`
+	ModifyTime                string        `description:"修改时间"`
+	CreateTime                string        `description:"创建时间"`
+	Button                    VarietyButton `description:"操作按钮权限"`
+}
+
+type VarietyButton struct {
+	Edit    bool `description:"操作权限"`
+	Delete  bool `description:"删除权限"`
+	Analyse bool `description:"分析权限"`
+}
+
+// GetListBySuperAdminPage 不区分是否有分析权限的获取分页数据
+func (item Variety) GetListBySuperAdminPage(condition string, pars []interface{}, startSize, pageSize int) (total int, items []*VarietyItem, err error) {
+	o := orm.NewOrm()
+	baseSql := ` FROM ( SELECT a.*, GROUP_CONCAT(DISTINCT b.sys_user_id ORDER BY b.sys_user_id ASC SEPARATOR ',') AS permission_user_id FROM variety a 
+				LEFT JOIN variety_admin_permission b on a.variety_id=b.variety_id 
+				LEFT JOIN variety_edb_info c on a.variety_id=c.variety_id WHERE 1=1 `
+	if condition != "" {
+		baseSql += condition
+	}
+	baseSql += ` GROUP BY a.variety_id ) d `
+	// 数据总数
+	totalSql := `SELECT COUNT(1) total ` + baseSql
+	err = o.Raw(totalSql, pars).QueryRow(&total)
+	if err != nil {
+		return
+	}
+
+	// 列表页数据
+	listSql := `SELECT * ` + baseSql + ` ORDER BY modify_time DESC,variety_id DESC LIMIT ?,?`
+	_, err = o.Raw(listSql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// GetListByPage 获取分页数据
+func (item Variety) GetListByPage(condition string, pars []interface{}, startSize, pageSize int) (total int, items []*VarietyItem, err error) {
+	o := orm.NewOrm()
+	baseSql := ` FROM ( SELECT a.*, GROUP_CONCAT(DISTINCT b.sys_user_id ORDER BY b.sys_user_id ASC SEPARATOR ',') AS permission_user_id FROM variety a 
+				JOIN variety_admin_permission b on a.variety_id=b.variety_id 
+				JOIN variety_edb_info c on a.variety_id=c.variety_id WHERE 1=1 `
+	if condition != "" {
+		baseSql += condition
+	}
+	baseSql += ` GROUP BY a.variety_id ) d `
+	// 数据总数
+	totalSql := `SELECT COUNT(1) total ` + baseSql
+	err = o.Raw(totalSql, pars).QueryRow(&total)
+	if err != nil {
+		return
+	}
+
+	// 列表页数据
+	listSql := `SELECT * ` + baseSql + ` ORDER BY modify_time DESC,variety_id DESC LIMIT ?,?`
+	_, err = o.Raw(listSql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// Update 更基础信息
+func (variety *Variety) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(variety, cols...)
+	return
+}
+
+// GetVarietyMaxSort 获取图表分类下最大的排序数
+func GetVarietyMaxSort(parentId int) (sort int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT Max(sort) AS sort FROM future_good_chart_classify WHERE parent_id=? AND is_delete=0 `
+	err = o.Raw(sql, parentId).QueryRow(&sort)
+	return
+}
+
+type VarietyView struct {
+	VarietyId   int    `orm:"column(future_good_chart_classify_id);pk"`
+	VarietyName string `description:"分类名称"`
+	ParentId    int    `description:"父级id"`
+}
+
+func GetVarietyViewById(classifyId int) (item *VarietyView, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM future_good_chart_classify WHERE future_good_chart_classify_id=? AND is_delete=0 `
+	err = o.Raw(sql, classifyId).QueryRow(&item)
+	return
+}

+ 22 - 0
models/supply_analysis/variety_admin_permission.go

@@ -0,0 +1,22 @@
+package supply_analysis
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// VarietyAdminPermission variety_admin_permission 品种权限表
+type VarietyAdminPermission struct {
+	Id         int       `orm:"column(id);pk"`
+	VarietyId  int       `description:"品种id"`
+	SysUserId  int       `description:"用户id"`
+	CreateTime time.Time `description:"添加时间"`
+}
+
+// GetVarietyPermissionByVarietyIdAndUserId 根据品种id和用户id获取权限记录表
+func GetVarietyPermissionByVarietyIdAndUserId(varietyId, sysUserId int) (item *VarietyAdminPermission, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM variety_admin_permission a  WHERE variety_id = ? AND sys_user_id = ? ORDER BY id desc `
+	err = o.Raw(sql, varietyId, sysUserId).QueryRow(&item)
+	return
+}

+ 101 - 0
models/supply_analysis/variety_edb_info.go

@@ -0,0 +1,101 @@
+package supply_analysis
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// VarietyEdbInfo variety_edb_info 品种指标表
+type VarietyEdbInfo struct {
+	VarietyEdbId int       `orm:"column(variety_edb_id);pk"`
+	VarietyId    int       `description:"品种id"`
+	EdbName      string    `description:"品种指标名称"`
+	Frequency    string    `description:"频度"`
+	StartDate    time.Time `description:"开始日期"`
+	EndDate      time.Time `description:"结束日期"`
+	LatestValue  float64   `description:"最新值"`
+	EdbInfoId    int       `description:"指标id"`
+	EdbCode      string    `description:"品种编码"`
+	Source       int       `description:"来源,1:影响周度产量;2:周度产量变动;3:影响月度产量;4:月度产量变动"`
+	ModifyTime   time.Time `description:"更新时间"`
+	CreateTime   time.Time `description:"添加时间"`
+}
+
+// GetAllVarietyEdbInfoByVarietyId 根据品种id获取所有的指标
+func GetAllVarietyEdbInfoByVarietyId(varietyId int) (items []*VarietyEdbInfo, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM variety_edb_info AS a WHERE a.variety_id = ? ORDER BY a.variety_edb_id ASC `
+	_, err = o.Raw(sql, varietyId).QueryRows(&items)
+	return
+}
+
+// GetVarietyEdbInfoByEdbInfoId 根据ETA指标库中的指标id获取指标
+func GetVarietyEdbInfoByEdbInfoId(varietyId int) (item *VarietyEdbInfo, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM variety_edb_info AS a WHERE a.edb_info_id = ? ORDER BY a.variety_edb_id ASC `
+	err = o.Raw(sql, varietyId).QueryRow(&item)
+
+	return
+}
+
+// BatchCreateVarietyEdbInfo 批量插入
+func BatchCreateVarietyEdbInfo(list []*VarietyEdbInfo) (err error) {
+	num := len(list)
+	if num <= 0 {
+		return
+	}
+
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(num, list)
+
+	return
+}
+
+// GetCountVarietyEdbByVarietyId 根据品种id获取添加到已经生成的指标数量(不管是否加入到ETA指标库)
+func GetCountVarietyEdbByVarietyId(varietyId int) (total int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT count(1) total FROM variety_edb_info AS a WHERE a.variety_id = ?`
+	err = o.Raw(sql, varietyId).QueryRow(&total)
+	return
+}
+
+// GetCountVarietyEdbInfoByVarietyId 根据品种id获取添加到ETA指标库的指标数量
+func GetCountVarietyEdbInfoByVarietyId(varietyId int) (total int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT count(1) total FROM variety_edb_info AS a
+			JOIN edb_info b on a.edb_info_id=b.edb_info_id
+			WHERE a.variety_id = ? and a.edb_info_id >0`
+	err = o.Raw(sql, varietyId).QueryRow(&total)
+	return
+}
+
+// VarietyEdbInfoItem 品种指标表(展示使用)
+type VarietyEdbInfoItem struct {
+	VarietyEdbId int                  `orm:"column(variety_edb_id);pk"`
+	VarietyId    int                  `description:"品种id"`
+	EdbName      string               `description:"品种指标名称"`
+	Frequency    string               `description:"频度"`
+	StartDate    string               `description:"开始日期"`
+	EndDate      string               `description:"结束日期"`
+	EdbInfoId    int                  `description:"指标id" json:"-"`
+	EdbCode      string               `description:"品种编码"`
+	ClassifyName string               `description:"分类名称"`
+	Source       int                  `description:"来源,1:影响周度产量;2:周度产量变动;3:影响月度产量;4:月度产量变动" json:"-"`
+	ModifyTime   string               `description:"最近一次更新时间"`
+	CreateTime   string               `description:"添加时间"`
+	Button       VarietyEdbInfoButton `description:"操作按钮权限"`
+}
+
+type VarietyEdbInfoButton struct {
+	Copy bool `description:"复制数据权限"`
+	Show bool `description:"查看数据权限"`
+	Add  bool `description:"添加到指标库"`
+}
+
+// GetAllVarietyEdbInfoItemByVarietyId 根据品种id获取所有的指标
+func GetAllVarietyEdbInfoItemByVarietyId(varietyId int) (items []*VarietyEdbInfoItem, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM variety_edb_info AS a WHERE a.variety_id = ? ORDER BY a.variety_edb_id ASC `
+	_, err = o.Raw(sql, varietyId).QueryRows(&items)
+	return
+}

+ 109 - 0
models/supply_analysis/variety_plant.go

@@ -0,0 +1,109 @@
+package supply_analysis
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// VarietyPlant variety_plant 品种装置表
+type VarietyPlant struct {
+	VarietyPlantId                int       `orm:"column(variety_plant_id);pk"`
+	VarietyId                     int       `description:"品种id"`
+	Province                      string    `description:"所属省份"`
+	City                          string    `description:"所属城市"`
+	FactoryName                   string    `description:"工厂名称"`
+	PlantName                     string    `description:"装置/产线名称"`
+	MaintenanceDate               time.Time `description:"检修日期"`
+	ResumptionDate                time.Time `description:"复产日期"`
+	AnnualCapacity                float64   `description:"年产能"`
+	Coefficient                   float64   `description:"降负系数"`
+	AverageDailyCapacityReduction float64   `description:"日均产量减量"`
+	SysUserId                     int       `description:"添加人id"`
+	SysUserRealName               string    `description:"添加人真实姓名"`
+	ModifyTime                    time.Time `description:"最近一次更新时间"`
+	CreateTime                    time.Time `description:"添加时间"`
+}
+
+// GetAllVarietyPlantByVarietyId 根据品种id获取所有的装置
+func GetAllVarietyPlantByVarietyId(varietyId int) (items []*VarietyPlant, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM variety_plant a  WHERE variety_id = ? ORDER BY variety_plant_id desc `
+	_, err = o.Raw(sql, varietyId).QueryRows(&items)
+	return
+}
+
+// AddVarietyPlant 添加future_good_chart分类
+func AddVarietyPlant(item *VarietyPlant) (err error) {
+	o := orm.NewOrm()
+	lastId, err := o.Insert(item)
+	if err != nil {
+		return
+	}
+	item.VarietyPlantId = int(lastId)
+
+	return
+}
+
+// Update 更新基础信息
+func (varietyPlant *VarietyPlant) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(varietyPlant, cols...)
+	return
+}
+
+// GetVarietyPlantById 根据品种装置id获取品种装置详情
+func GetVarietyPlantById(id int) (item *VarietyPlant, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM variety_plant WHERE variety_plant_id = ?`
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+// VarietyPlantItem 品种装置数据(展示使用)
+type VarietyPlantItem struct {
+	VarietyPlantId                int                `orm:"column(variety_plant_id);pk"`
+	VarietyId                     int                `description:"品种id"`
+	Province                      string             `description:"所属省份"`
+	City                          string             `description:"所属城市"`
+	FactoryName                   string             `description:"工厂名称"`
+	PlantName                     string             `description:"装置/产线名称"`
+	MaintenanceDate               string             `description:"检修日期"`
+	ResumptionDate                string             `description:"复产日期"`
+	AnnualCapacity                float64            `description:"年产能"`
+	Coefficient                   float64            `description:"降负系数"`
+	AverageDailyCapacityReduction float64            `description:"日均产量减量"`
+	SysUserId                     int                `description:"添加人id"`
+	SysUserRealName               string             `description:"添加人真实姓名"`
+	ModifyTime                    string             `description:"最近一次更新时间"`
+	CreateTime                    string             `description:"添加时间"`
+	Button                        VarietyPlantButton `description:"操作按钮权限"`
+}
+
+type VarietyPlantButton struct {
+	Edit   bool `description:"操作权限"`
+	Delete bool `description:"删除权限"`
+}
+
+// GetAllVarietyPlantItemByVarietyId 根据品种id获取所有的装置
+func GetAllVarietyPlantItemByVarietyId(varietyId int) (items []*VarietyPlantItem, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM variety_plant a  WHERE variety_id = ? ORDER BY variety_plant_id desc `
+	_, err = o.Raw(sql, varietyId).QueryRows(&items)
+	return
+}
+
+// GetCountVarietyPlantByVarietyId 根据品种id获取所有的装置数量
+func GetCountVarietyPlantByVarietyId(varietyId int) (total int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT count(1) total FROM variety_plant a  WHERE variety_id = ? `
+	err = o.Raw(sql, varietyId).QueryRow(&total)
+	return
+}
+
+// DeleteVarietyPlantById 根据装置id删除
+func DeleteVarietyPlantById(id int) (err error) {
+	o := orm.NewOrm()
+	sql := `DELETE FROM variety_plant WHERE variety_plant_id = ?`
+	_, err = o.Raw(sql, id).Exec()
+	return
+}

+ 18 - 0
routers/commentsRouter.go

@@ -493,6 +493,24 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hongze_edb_lib/controllers:StockPlantController"] = append(beego.GlobalControllerRouter["hongze/hongze_edb_lib/controllers:StockPlantController"],
+        beego.ControllerComments{
+            Method: "Calculate",
+            Router: `/calculate`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_edb_lib/controllers:StockPlantController"] = append(beego.GlobalControllerRouter["hongze/hongze_edb_lib/controllers:StockPlantController"],
+        beego.ControllerComments{
+            Method: "Refresh",
+            Router: `/refresh`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hongze_edb_lib/controllers:ThsController"] = append(beego.GlobalControllerRouter["hongze/hongze_edb_lib/controllers:ThsController"],
         beego.ControllerComments{
             Method: "Add",

+ 5 - 0
routers/router.go

@@ -150,6 +150,11 @@ func init() {
 				&controllers.BaiinfoController{},
 			),
 		),
+		beego.NSNamespace("/stock_plant",
+			beego.NSInclude(
+				&controllers.StockPlantController{},
+			),
+		),
 	)
 	beego.AddNamespace(ns)
 }

+ 5 - 4
utils/constants.go

@@ -191,8 +191,9 @@ const (
 )
 
 const (
-	CACHE_EDB_DATA_ADD     = "CACHE_EDB_DATA_ADD_"
-	CACHE_EDB_DATA_REFRESH = "CACHE_EDB_DATA_REFRESH_"
-	CACHE_WIND_URL         = "CACHE_WIND_URL"
-	CACHE_CHART_INFO_DATA  = "chart:info:data:" //图表数据
+	CACHE_EDB_DATA_ADD          = "CACHE_EDB_DATA_ADD_"
+	CACHE_EDB_DATA_REFRESH      = "CACHE_EDB_DATA_REFRESH_"
+	CACHE_WIND_URL              = "CACHE_WIND_URL"
+	CACHE_CHART_INFO_DATA       = "chart:info:data:"             //图表数据
+	CACHE_STOCK_PLANT_CALCULATE = "CACHE_STOCK_PLANT_CALCULATE_" // 库存装置减产计算
 )