issue_29 #32

Merged
huang merged 65 commits from issue_29 into main 2025-10-07 13:33:25 +08:00
6 changed files with 46 additions and 22 deletions
Showing only changes of commit 6cc6d719e1 - Show all commits

View File

@@ -0,0 +1 @@
package service

View File

@@ -165,11 +165,13 @@ func (ps *PostgresStorage) creatingHyperTable() error {
{models.FeedUsageRecord{}, "recorded_at"}, {models.FeedUsageRecord{}, "recorded_at"},
{models.GroupMedicationLog{}, "happened_at"}, {models.GroupMedicationLog{}, "happened_at"},
{models.PigBatchLog{}, "happened_at"}, {models.PigBatchLog{}, "happened_at"},
{models.WeighingBatch{}, "weighing_time"},
{models.WeighingRecord{}, "weighing_time"},
} }
for _, table := range tablesToConvert { for _, table := range tablesToConvert {
tableName := table.model.TableName() tableName := table.model.TableName()
chunkInterval := "7 days" // 统一设置为7 chunkInterval := "1 days" // 统一设置为1
ps.logger.Infow("准备将表转换为超表", "table", tableName, "chunk_interval", chunkInterval) ps.logger.Infow("准备将表转换为超表", "table", tableName, "chunk_interval", chunkInterval)
sql := fmt.Sprintf("SELECT create_hypertable('%s', '%s', chunk_time_interval => INTERVAL '%s', if_not_exists => TRUE);", tableName, table.timeColumn, chunkInterval) sql := fmt.Sprintf("SELECT create_hypertable('%s', '%s', chunk_time_interval => INTERVAL '%s', if_not_exists => TRUE);", tableName, table.timeColumn, chunkInterval)
if err := ps.db.Exec(sql).Error; err != nil { if err := ps.db.Exec(sql).Error; err != nil {
@@ -194,11 +196,18 @@ func (ps *PostgresStorage) applyCompressionPolicies() error {
{models.TaskExecutionLog{}, "task_id"}, {models.TaskExecutionLog{}, "task_id"},
{models.PendingCollection{}, "device_id"}, {models.PendingCollection{}, "device_id"},
{models.UserActionLog{}, "user_id"}, {models.UserActionLog{}, "user_id"},
{models.RawMaterialPurchase{}, "raw_material_id"},
{models.RawMaterialStockLog{}, "raw_material_id"},
{models.FeedUsageRecord{}, "pen_id"},
{models.GroupMedicationLog{}, "pig_batch_id"},
{models.PigBatchLog{}, "pig_batch_id"},
{models.WeighingBatch{}, "pig_batch_id"},
{models.WeighingRecord{}, "weighing_batch_id"},
} }
for _, policy := range policies { for _, policy := range policies {
tableName := policy.model.TableName() tableName := policy.model.TableName()
compressAfter := "15 days" // 统一设置为15天后开始压缩 compressAfter := "3 days" // 统一设置为2天后即进入第3天开始压缩
// 1. 开启表的压缩设置,并指定分段列 // 1. 开启表的压缩设置,并指定分段列
ps.logger.Infow("为表启用压缩设置", "table", tableName, "segment_by", policy.segmentColumn) ps.logger.Infow("为表启用压缩设置", "table", tableName, "segment_by", policy.segmentColumn)

View File

@@ -25,7 +25,7 @@ func (RawMaterial) TableName() string {
// RawMaterialPurchase 记录了原料的每一次采购。 // RawMaterialPurchase 记录了原料的每一次采购。
type RawMaterialPurchase struct { type RawMaterialPurchase struct {
ID uint `gorm:"primaryKey"` gorm.Model
RawMaterialID uint `gorm:"not null;index;comment:关联的原料ID"` RawMaterialID uint `gorm:"not null;index;comment:关联的原料ID"`
RawMaterial RawMaterial `gorm:"foreignKey:RawMaterialID"` RawMaterial RawMaterial `gorm:"foreignKey:RawMaterialID"`
Supplier string `gorm:"size:100;comment:供应商"` Supplier string `gorm:"size:100;comment:供应商"`
@@ -34,8 +34,6 @@ type RawMaterialPurchase struct {
TotalPrice float64 `gorm:"comment:总价"` TotalPrice float64 `gorm:"comment:总价"`
PurchaseDate time.Time `gorm:"primaryKey;comment:采购日期"` PurchaseDate time.Time `gorm:"primaryKey;comment:采购日期"`
CreatedAt time.Time CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
} }
func (RawMaterialPurchase) TableName() string { func (RawMaterialPurchase) TableName() string {
@@ -56,16 +54,13 @@ const (
// RawMaterialStockLog 记录了原料库存的所有变动,提供了完整的追溯链。 // RawMaterialStockLog 记录了原料库存的所有变动,提供了完整的追溯链。
type RawMaterialStockLog struct { type RawMaterialStockLog struct {
ID uint `gorm:"primaryKey"` gorm.Model
RawMaterialID uint `gorm:"not null;index;comment:关联的原料ID"` RawMaterialID uint `gorm:"not null;index;comment:关联的原料ID"`
ChangeAmount float64 `gorm:"not null;comment:变动数量, 正数为入库, 负数为出库"` ChangeAmount float64 `gorm:"not null;comment:变动数量, 正数为入库, 负数为出库"`
SourceType StockLogSourceType `gorm:"size:50;not null;index;comment:库存变动来源类型"` SourceType StockLogSourceType `gorm:"size:50;not null;index;comment:库存变动来源类型"`
SourceID uint `gorm:"not null;index;comment:来源记录的ID (如 RawMaterialPurchase.ID 或 FeedUsageRecord.ID)"` SourceID uint `gorm:"not null;index;comment:来源记录的ID (如 RawMaterialPurchase.ID 或 FeedUsageRecord.ID)"`
HappenedAt time.Time `gorm:"primaryKey;comment:业务发生时间"` HappenedAt time.Time `gorm:"primaryKey;comment:业务发生时间"`
Remarks string `gorm:"comment:备注, 如主动领取的理由等"` Remarks string `gorm:"comment:备注, 如主动领取的理由等"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
} }
func (RawMaterialStockLog) TableName() string { func (RawMaterialStockLog) TableName() string {
@@ -102,7 +97,7 @@ func (FeedFormulaComponent) TableName() string {
// 应用层逻辑:当一条使用记录被创建时,应根据其使用的 FeedFormula, // 应用层逻辑:当一条使用记录被创建时,应根据其使用的 FeedFormula,
// 计算出每种 RawMaterial 的消耗量,并在 RawMaterialStockLog 中创建对应的出库记录。 // 计算出每种 RawMaterial 的消耗量,并在 RawMaterialStockLog 中创建对应的出库记录。
type FeedUsageRecord struct { type FeedUsageRecord struct {
ID uint `gorm:"primaryKey"` gorm.Model
PenID uint `gorm:"not null;index;comment:关联的猪栏ID"` PenID uint `gorm:"not null;index;comment:关联的猪栏ID"`
Pen Pen `gorm:"foreignKey:PenID"` Pen Pen `gorm:"foreignKey:PenID"`
FeedFormulaID uint `gorm:"not null;index;comment:使用的饲料配方ID"` FeedFormulaID uint `gorm:"not null;index;comment:使用的饲料配方ID"`
@@ -111,9 +106,6 @@ type FeedUsageRecord struct {
RecordedAt time.Time `gorm:"primaryKey;comment:记录时间"` RecordedAt time.Time `gorm:"primaryKey;comment:记录时间"`
OperatorID uint `gorm:"not null;comment:操作员"` OperatorID uint `gorm:"not null;comment:操作员"`
Remarks string `gorm:"comment:备注, 如 '例行喂料, 弱猪补料' 等"` Remarks string `gorm:"comment:备注, 如 '例行喂料, 弱猪补料' 等"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
} }
func (FeedUsageRecord) TableName() string { func (FeedUsageRecord) TableName() string {

View File

@@ -82,7 +82,7 @@ const (
// GroupMedicationLog 记录了对整个猪批次的用药情况 // GroupMedicationLog 记录了对整个猪批次的用药情况
type GroupMedicationLog struct { type GroupMedicationLog struct {
ID uint `gorm:"primaryKey"` gorm.Model
PigBatchID uint `gorm:"not null;index;comment:关联的猪批次ID"` PigBatchID uint `gorm:"not null;index;comment:关联的猪批次ID"`
MedicationID uint `gorm:"not null;index;comment:关联的药品ID"` MedicationID uint `gorm:"not null;index;comment:关联的药品ID"`
Medication Medication `gorm:"foreignKey:MedicationID"` // 预加载药品信息 Medication Medication `gorm:"foreignKey:MedicationID"` // 预加载药品信息
@@ -92,9 +92,6 @@ type GroupMedicationLog struct {
Description string `gorm:"size:255;comment:具体描述,如'治疗呼吸道病'"` Description string `gorm:"size:255;comment:具体描述,如'治疗呼吸道病'"`
Operator string `gorm:"size:50;comment:操作员"` Operator string `gorm:"size:50;comment:操作员"`
HappenedAt time.Time `gorm:"primaryKey;comment:用药时间"` HappenedAt time.Time `gorm:"primaryKey;comment:用药时间"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
} }
func (GroupMedicationLog) TableName() string { func (GroupMedicationLog) TableName() string {

View File

@@ -39,6 +39,8 @@ func GetAllModels() []interface{} {
// Pig & Batch Models // Pig & Batch Models
&PigBatch{}, &PigBatch{},
&PigBatchLog{}, &PigBatchLog{},
&WeighingBatch{},
&WeighingRecord{},
// Feed Models // Feed Models
&RawMaterial{}, &RawMaterial{},

View File

@@ -39,7 +39,6 @@ type PigBatch struct {
InitialCount int `gorm:"not null;comment:初始数量"` InitialCount int `gorm:"not null;comment:初始数量"`
CurrentCount int `gorm:"not null;comment:当前存栏数量"` CurrentCount int `gorm:"not null;comment:当前存栏数量"`
CurrentSickCount int `gorm:"not null;default:0;comment:当前病猪数量"` CurrentSickCount int `gorm:"not null;default:0;comment:当前病猪数量"`
AverageWeight float64 `gorm:"comment:平均体重 (kg)"`
Status PigBatchStatus `gorm:"size:20;not null;index;comment:批次状态"` Status PigBatchStatus `gorm:"size:20;not null;index;comment:批次状态"`
Pens []Pen `gorm:"foreignKey:PigBatchID;comment:所在圈舍ID"` Pens []Pen `gorm:"foreignKey:PigBatchID;comment:所在圈舍ID"`
} }
@@ -64,7 +63,7 @@ const (
// PigBatchLog 记录了猪批次数量或状态的每一次变更 // PigBatchLog 记录了猪批次数量或状态的每一次变更
type PigBatchLog struct { type PigBatchLog struct {
ID uint `gorm:"primaryKey"` gorm.Model
PigBatchID uint `gorm:"not null;index;comment:关联的猪批次ID"` PigBatchID uint `gorm:"not null;index;comment:关联的猪批次ID"`
ChangeType LogChangeType `gorm:"size:20;not null;comment:变更类型"` ChangeType LogChangeType `gorm:"size:20;not null;comment:变更类型"`
ChangeCount int `gorm:"not null;comment:数量变化,负数表示减少"` ChangeCount int `gorm:"not null;comment:数量变化,负数表示减少"`
@@ -75,11 +74,35 @@ type PigBatchLog struct {
AfterSickCount int `gorm:"not null;comment:变更后病猪数"` AfterSickCount int `gorm:"not null;comment:变更后病猪数"`
Operator string `gorm:"size:50;comment:操作员"` Operator string `gorm:"size:50;comment:操作员"`
HappenedAt time.Time `gorm:"primaryKey;comment:事件发生时间"` HappenedAt time.Time `gorm:"primaryKey;comment:事件发生时间"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
} }
func (PigBatchLog) TableName() string { func (PigBatchLog) TableName() string {
return "pig_batch_logs" return "pig_batch_logs"
} }
// WeighingBatch 记录了一次批次称重的信息
type WeighingBatch struct {
gorm.Model
WeighingTime time.Time `gorm:"primaryKey;comment:称重时间"`
Description string `gorm:"size:255;comment:批次称重描述"`
PigBatchID uint `gorm:"not null;index;comment:关联的猪批次ID"`
}
func (WeighingBatch) TableName() string {
return "weighing_batches"
}
// WeighingRecord 记录了单次称重信息
type WeighingRecord struct {
gorm.Model
Weight float64 `gorm:"not null;comment:单只猪重量 (kg)"`
WeighingBatchID uint `gorm:"not null;index;comment:关联的批次称重ID"`
PenID uint `gorm:"not null;index;comment:所在猪圈ID"`
OperatorID uint `gorm:"not null;comment:操作员ID"`
Remark string `gorm:"size:255;comment:备注"`
WeighingTime time.Time `gorm:"primaryKey;comment:称重时间"`
}
func (WeighingRecord) TableName() string {
return "weighing_records"
}