实现按原料是否有库存筛选

This commit is contained in:
2025-11-27 17:33:28 +08:00
parent e6b307b0dc
commit 3b12802900
7 changed files with 93 additions and 22 deletions

View File

@@ -3392,6 +3392,12 @@ const docTemplate = `{
], ],
"summary": "获取当前库存列表", "summary": "获取当前库存列表",
"parameters": [ "parameters": [
{
"type": "boolean",
"description": "只查询有库存的原料",
"name": "has_stock",
"in": "query"
},
{ {
"type": "string", "type": "string",
"description": "排序字段, 例如 \"stock DESC\"", "description": "排序字段, 例如 \"stock DESC\"",
@@ -3715,6 +3721,7 @@ const docTemplate = `{
}, },
{ {
"enum": [ "enum": [
7,
-1, -1,
0, 0,
1, 1,
@@ -3724,12 +3731,12 @@ const docTemplate = `{
5, 5,
-1, -1,
5, 5,
6, 6
7
], ],
"type": "integer", "type": "integer",
"format": "int32", "format": "int32",
"x-enum-varnames": [ "x-enum-varnames": [
"_numLevels",
"DebugLevel", "DebugLevel",
"InfoLevel", "InfoLevel",
"WarnLevel", "WarnLevel",
@@ -3739,8 +3746,7 @@ const docTemplate = `{
"FatalLevel", "FatalLevel",
"_minLevel", "_minLevel",
"_maxLevel", "_maxLevel",
"InvalidLevel", "InvalidLevel"
"_numLevels"
], ],
"name": "level", "name": "level",
"in": "query" "in": "query"
@@ -7267,6 +7273,10 @@ const docTemplate = `{
"type": "string", "type": "string",
"maxLength": 255 "maxLength": 255
}, },
"max_addition_ratio": {
"description": "最大添加比例",
"type": "number"
},
"name": { "name": {
"description": "原料名称", "description": "原料名称",
"type": "string", "type": "string",
@@ -8824,6 +8834,10 @@ const docTemplate = `{
"id": { "id": {
"type": "integer" "type": "integer"
}, },
"max_addition_ratio": {
"description": "最大添加比例",
"type": "number"
},
"name": { "name": {
"type": "string" "type": "string"
}, },
@@ -9864,6 +9878,10 @@ const docTemplate = `{
"type": "string", "type": "string",
"maxLength": 255 "maxLength": 255
}, },
"max_addition_ratio": {
"description": "最大添加比例",
"type": "number"
},
"name": { "name": {
"description": "原料名称", "description": "原料名称",
"type": "string", "type": "string",
@@ -10586,6 +10604,7 @@ const docTemplate = `{
"type": "integer", "type": "integer",
"format": "int32", "format": "int32",
"enum": [ "enum": [
7,
-1, -1,
0, 0,
1, 1,
@@ -10595,10 +10614,10 @@ const docTemplate = `{
5, 5,
-1, -1,
5, 5,
6, 6
7
], ],
"x-enum-varnames": [ "x-enum-varnames": [
"_numLevels",
"DebugLevel", "DebugLevel",
"InfoLevel", "InfoLevel",
"WarnLevel", "WarnLevel",
@@ -10608,8 +10627,7 @@ const docTemplate = `{
"FatalLevel", "FatalLevel",
"_minLevel", "_minLevel",
"_maxLevel", "_maxLevel",
"InvalidLevel", "InvalidLevel"
"_numLevels"
] ]
} }
}, },

View File

@@ -3384,6 +3384,12 @@
], ],
"summary": "获取当前库存列表", "summary": "获取当前库存列表",
"parameters": [ "parameters": [
{
"type": "boolean",
"description": "只查询有库存的原料",
"name": "has_stock",
"in": "query"
},
{ {
"type": "string", "type": "string",
"description": "排序字段, 例如 \"stock DESC\"", "description": "排序字段, 例如 \"stock DESC\"",
@@ -3707,6 +3713,7 @@
}, },
{ {
"enum": [ "enum": [
7,
-1, -1,
0, 0,
1, 1,
@@ -3716,12 +3723,12 @@
5, 5,
-1, -1,
5, 5,
6, 6
7
], ],
"type": "integer", "type": "integer",
"format": "int32", "format": "int32",
"x-enum-varnames": [ "x-enum-varnames": [
"_numLevels",
"DebugLevel", "DebugLevel",
"InfoLevel", "InfoLevel",
"WarnLevel", "WarnLevel",
@@ -3731,8 +3738,7 @@
"FatalLevel", "FatalLevel",
"_minLevel", "_minLevel",
"_maxLevel", "_maxLevel",
"InvalidLevel", "InvalidLevel"
"_numLevels"
], ],
"name": "level", "name": "level",
"in": "query" "in": "query"
@@ -7259,6 +7265,10 @@
"type": "string", "type": "string",
"maxLength": 255 "maxLength": 255
}, },
"max_addition_ratio": {
"description": "最大添加比例",
"type": "number"
},
"name": { "name": {
"description": "原料名称", "description": "原料名称",
"type": "string", "type": "string",
@@ -8816,6 +8826,10 @@
"id": { "id": {
"type": "integer" "type": "integer"
}, },
"max_addition_ratio": {
"description": "最大添加比例",
"type": "number"
},
"name": { "name": {
"type": "string" "type": "string"
}, },
@@ -9856,6 +9870,10 @@
"type": "string", "type": "string",
"maxLength": 255 "maxLength": 255
}, },
"max_addition_ratio": {
"description": "最大添加比例",
"type": "number"
},
"name": { "name": {
"description": "原料名称", "description": "原料名称",
"type": "string", "type": "string",
@@ -10578,6 +10596,7 @@
"type": "integer", "type": "integer",
"format": "int32", "format": "int32",
"enum": [ "enum": [
7,
-1, -1,
0, 0,
1, 1,
@@ -10587,10 +10606,10 @@
5, 5,
-1, -1,
5, 5,
6, 6
7
], ],
"x-enum-varnames": [ "x-enum-varnames": [
"_numLevels",
"DebugLevel", "DebugLevel",
"InfoLevel", "InfoLevel",
"WarnLevel", "WarnLevel",
@@ -10600,8 +10619,7 @@
"FatalLevel", "FatalLevel",
"_minLevel", "_minLevel",
"_maxLevel", "_maxLevel",
"InvalidLevel", "InvalidLevel"
"_numLevels"
] ]
} }
}, },

View File

@@ -416,6 +416,9 @@ definitions:
description: 描述 description: 描述
maxLength: 255 maxLength: 255
type: string type: string
max_addition_ratio:
description: 最大添加比例
type: number
name: name:
description: 原料名称 description: 原料名称
maxLength: 100 maxLength: 100
@@ -1446,6 +1449,9 @@ definitions:
type: string type: string
id: id:
type: integer type: integer
max_addition_ratio:
description: 最大添加比例
type: number
name: name:
type: string type: string
raw_material_nutrients: raw_material_nutrients:
@@ -2160,6 +2166,9 @@ definitions:
description: 描述 description: 描述
maxLength: 255 maxLength: 255
type: string type: string
max_addition_ratio:
description: 最大添加比例
type: number
name: name:
description: 原料名称 description: 原料名称
maxLength: 100 maxLength: 100
@@ -2731,6 +2740,7 @@ definitions:
- PlanTypeFilterSystem - PlanTypeFilterSystem
zapcore.Level: zapcore.Level:
enum: enum:
- 7
- -1 - -1
- 0 - 0
- 1 - 1
@@ -2741,10 +2751,10 @@ definitions:
- -1 - -1
- 5 - 5
- 6 - 6
- 7
format: int32 format: int32
type: integer type: integer
x-enum-varnames: x-enum-varnames:
- _numLevels
- DebugLevel - DebugLevel
- InfoLevel - InfoLevel
- WarnLevel - WarnLevel
@@ -2755,7 +2765,6 @@ definitions:
- _minLevel - _minLevel
- _maxLevel - _maxLevel
- InvalidLevel - InvalidLevel
- _numLevels
info: info:
contact: contact:
email: divano@example.com email: divano@example.com
@@ -4793,6 +4802,10 @@ paths:
get: get:
description: 获取所有原料的当前库存列表,支持分页和过滤。 description: 获取所有原料的当前库存列表,支持分页和过滤。
parameters: parameters:
- description: 只查询有库存的原料
in: query
name: has_stock
type: boolean
- description: 排序字段, 例如 "stock DESC" - description: 排序字段, 例如 "stock DESC"
in: query in: query
name: order_by name: order_by
@@ -4985,6 +4998,7 @@ paths:
name: end_time name: end_time
type: string type: string
- enum: - enum:
- 7
- -1 - -1
- 0 - 0
- 1 - 1
@@ -4995,12 +5009,12 @@ paths:
- -1 - -1
- 5 - 5
- 6 - 6
- 7
format: int32 format: int32
in: query in: query
name: level name: level
type: integer type: integer
x-enum-varnames: x-enum-varnames:
- _numLevels
- DebugLevel - DebugLevel
- InfoLevel - InfoLevel
- WarnLevel - WarnLevel
@@ -5011,7 +5025,6 @@ paths:
- _minLevel - _minLevel
- _maxLevel - _maxLevel
- InvalidLevel - InvalidLevel
- _numLevels
- enum: - enum:
- 邮件 - 邮件
- 企业微信 - 企业微信

View File

@@ -31,6 +31,7 @@ type ListCurrentStockRequest struct {
PageSize int `json:"page_size" query:"page_size"` // 每页数量 PageSize int `json:"page_size" query:"page_size"` // 每页数量
RawMaterialName *string `json:"raw_material_name" query:"raw_material_name"` // 按原料名称模糊查询 RawMaterialName *string `json:"raw_material_name" query:"raw_material_name"` // 按原料名称模糊查询
OrderBy string `json:"order_by" query:"order_by"` // 排序字段, 例如 "stock DESC" OrderBy string `json:"order_by" query:"order_by"` // 排序字段, 例如 "stock DESC"
HasStock *bool `json:"has_stock" query:"has_stock"` // 只查询有库存的原料
} }
// ListCurrentStockResponse 是获取当前库存列表的响应结构 // ListCurrentStockResponse 是获取当前库存列表的响应结构

View File

@@ -77,6 +77,7 @@ func (s *inventoryServiceImpl) ListCurrentStock(ctx context.Context, req *dto.Li
rawMatOpts := repository.RawMaterialListOptions{ rawMatOpts := repository.RawMaterialListOptions{
Name: req.RawMaterialName, Name: req.RawMaterialName,
OrderBy: req.OrderBy, // 注意:这里的排序可能需要调整,比如按原料名排序 OrderBy: req.OrderBy, // 注意:这里的排序可能需要调整,比如按原料名排序
HasStock: req.HasStock,
} }
rawMaterials, total, err := s.rawMatRepo.ListRawMaterials(serviceCtx, rawMatOpts, req.Page, req.PageSize) rawMaterials, total, err := s.rawMatRepo.ListRawMaterials(serviceCtx, rawMatOpts, req.Page, req.PageSize)
if err != nil { if err != nil {

View File

@@ -18,6 +18,7 @@ type RawMaterialListOptions struct {
NutrientName *string NutrientName *string
MinReferencePrice *float32 // 参考价格最小值 MinReferencePrice *float32 // 参考价格最小值
MaxReferencePrice *float32 // 参考价格最大值 MaxReferencePrice *float32 // 参考价格最大值
HasStock *bool // 是否只查询有库存的原料
OrderBy string OrderBy string
} }
@@ -122,6 +123,22 @@ func (r *gormRawMaterialRepository) ListRawMaterials(ctx context.Context, opts R
db = db.Where("reference_price <= ?", *opts.MaxReferencePrice) db = db.Where("reference_price <= ?", *opts.MaxReferencePrice)
} }
// 筛选有库存的原料
if opts.HasStock != nil && *opts.HasStock {
// 内部子查询:生成带有 rn 的结果集GORM 会自动为 models.RawMaterialStockLog 添加 deleted_at IS NULL
rankedLogsQuery := r.db.Model(&models.RawMaterialStockLog{}).
Select("raw_material_id, after_quantity, ROW_NUMBER() OVER(PARTITION BY raw_material_id ORDER BY happened_at DESC, id DESC) as rn")
// 外部子查询:从 ranked_logs 中筛选 rn=1 且 after_quantity > 0 的 raw_material_id
// GORM 会将 rankedLogsQuery 作为一个子查询嵌入到 FROM 子句中
latestStockLogSubQuery := r.db.Table("(?) as ranked_logs", rankedLogsQuery).
Select("raw_material_id").
Where("rn = 1 AND after_quantity > 0")
// 将这个子查询直接应用到主查询的 WHERE id IN (?) 条件中
db = db.Where("id IN (?)", latestStockLogSubQuery)
}
// 首先计算总数 // 首先计算总数
if err := db.Count(&total).Error; err != nil { if err := db.Count(&total).Error; err != nil {
return nil, 0, err return nil, 0, err

View File

@@ -145,6 +145,9 @@ internal/domain/task/task.go
internal/infra/config/config.go internal/infra/config/config.go
internal/infra/database/postgres.go internal/infra/database/postgres.go
internal/infra/database/seeder.go internal/infra/database/seeder.go
internal/infra/database/seeder/nutrient_seeder.go
internal/infra/database/seeder/pig_nutrient_requirement_seeder.go
internal/infra/database/seeder/utils.go
internal/infra/database/storage.go internal/infra/database/storage.go
internal/infra/logs/context.go internal/infra/logs/context.go
internal/infra/logs/encoder.go internal/infra/logs/encoder.go