From e142405bb359a4b6660d6db3560453f816e862f2 Mon Sep 17 00:00:00 2001 From: huang <1724659546@qq.com> Date: Mon, 6 Oct 2025 23:22:47 +0800 Subject: [PATCH] =?UTF-8?q?=E7=8C=AA=E7=BE=A4=E9=A2=86=E5=9F=9F=E5=85=B6?= =?UTF-8?q?=E4=BB=96=E6=96=B9=E6=B3=95=E6=98=A0=E5=B0=84=E5=88=B0api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/docs.go | 784 +++++++++++++++++- docs/swagger.json | 784 +++++++++++++++++- docs/swagger.yaml | 544 +++++++++++- internal/app/api/api.go | 12 +- .../management/pig_batch_controller.go | 18 +- .../management/pig_batch_health_controller.go | 269 ++++++ .../management/pig_batch_trade_controller.go | 97 +++ .../pig_batch_transfer_controller.go | 97 +++ internal/app/dto/pig_batch_dto.go | 91 ++ internal/app/service/pig_batch_service.go | 122 +++ 10 files changed, 2783 insertions(+), 35 deletions(-) create mode 100644 internal/app/controller/management/pig_batch_health_controller.go create mode 100644 internal/app/controller/management/pig_batch_trade_controller.go create mode 100644 internal/app/controller/management/pig_batch_transfer_controller.go diff --git a/docs/docs.go b/docs/docs.go index d74aae3..cd81b29 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -867,7 +867,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "猪批次管理" + "猪群管理" ], "summary": "获取猪批次列表", "parameters": [ @@ -911,7 +911,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "猪批次管理" + "猪群管理" ], "summary": "创建猪批次", "parameters": [ @@ -954,7 +954,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "猪批次管理" + "猪群管理" ], "summary": "从猪批次移除空栏", "parameters": [ @@ -993,7 +993,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "猪批次管理" + "猪群管理" ], "summary": "将猪栏划拨到新批次", "parameters": [ @@ -1031,7 +1031,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "猪批次管理" + "猪群管理" ], "summary": "获取单个猪批次", "parameters": [ @@ -1073,7 +1073,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "猪批次管理" + "猪群管理" ], "summary": "更新猪批次", "parameters": [ @@ -1121,7 +1121,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "猪批次管理" + "猪群管理" ], "summary": "删除猪批次", "parameters": [ @@ -1153,7 +1153,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "猪批次管理" + "猪群管理" ], "summary": "为猪批次分配空栏", "parameters": [ @@ -1184,6 +1184,47 @@ const docTemplate = `{ } } }, + "/api/v1/pig-batches/{id}/buy-pigs": { + "post": { + "description": "记录猪批次中的猪只购买事件", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "猪批次管理" + ], + "summary": "处理买猪的业务逻辑", + "parameters": [ + { + "type": "integer", + "description": "猪批次ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "买猪请求信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.BuyPigsRequest" + } + } + ], + "responses": { + "200": { + "description": "买猪成功", + "schema": { + "$ref": "#/definitions/controller.Response" + } + } + } + } + }, "/api/v1/pig-batches/{id}/move-pigs-into-pen": { "post": { "description": "将指定数量的猪只从批次的“虚拟库存”移入一个已分配的猪栏", @@ -1194,7 +1235,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "猪批次管理" + "猪群管理" ], "summary": "将猪只从“虚拟库存”移入指定猪栏", "parameters": [ @@ -1225,6 +1266,375 @@ const docTemplate = `{ } } }, + "/api/v1/pig-batches/{id}/record-cull": { + "post": { + "description": "记录猪批次中正常猪只淘汰的数量和发生时间", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "猪批次管理" + ], + "summary": "记录正常猪只淘汰事件", + "parameters": [ + { + "type": "integer", + "description": "猪批次ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "记录正常猪只淘汰请求信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.RecordCullRequest" + } + } + ], + "responses": { + "200": { + "description": "记录成功", + "schema": { + "$ref": "#/definitions/controller.Response" + } + } + } + } + }, + "/api/v1/pig-batches/{id}/record-death": { + "post": { + "description": "记录猪批次中正常猪只死亡的数量和发生时间", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "猪批次管理" + ], + "summary": "记录正常猪只死亡事件", + "parameters": [ + { + "type": "integer", + "description": "猪批次ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "记录正常猪只死亡请求信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.RecordDeathRequest" + } + } + ], + "responses": { + "200": { + "description": "记录成功", + "schema": { + "$ref": "#/definitions/controller.Response" + } + } + } + } + }, + "/api/v1/pig-batches/{id}/record-sick-pig-cull": { + "post": { + "description": "记录猪批次中病猪淘汰的数量、治疗地点和发生时间", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "猪批次管理" + ], + "summary": "记录病猪淘汰事件", + "parameters": [ + { + "type": "integer", + "description": "猪批次ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "记录病猪淘汰请求信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.RecordSickPigCullRequest" + } + } + ], + "responses": { + "200": { + "description": "记录成功", + "schema": { + "$ref": "#/definitions/controller.Response" + } + } + } + } + }, + "/api/v1/pig-batches/{id}/record-sick-pig-death": { + "post": { + "description": "记录猪批次中病猪死亡的数量、治疗地点和发生时间", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "猪批次管理" + ], + "summary": "记录病猪死亡事件", + "parameters": [ + { + "type": "integer", + "description": "猪批次ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "记录病猪死亡请求信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.RecordSickPigDeathRequest" + } + } + ], + "responses": { + "200": { + "description": "记录成功", + "schema": { + "$ref": "#/definitions/controller.Response" + } + } + } + } + }, + "/api/v1/pig-batches/{id}/record-sick-pig-recovery": { + "post": { + "description": "记录猪批次中病猪康复的数量、治疗地点和发生时间", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "猪批次管理" + ], + "summary": "记录病猪康复事件", + "parameters": [ + { + "type": "integer", + "description": "猪批次ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "记录病猪康复请求信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.RecordSickPigRecoveryRequest" + } + } + ], + "responses": { + "200": { + "description": "记录成功", + "schema": { + "$ref": "#/definitions/controller.Response" + } + } + } + } + }, + "/api/v1/pig-batches/{id}/record-sick-pigs": { + "post": { + "description": "记录猪批次中新增病猪的数量、治疗地点和发生时间", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "猪批次管理" + ], + "summary": "记录新增病猪事件", + "parameters": [ + { + "type": "integer", + "description": "猪批次ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "记录病猪请求信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.RecordSickPigsRequest" + } + } + ], + "responses": { + "200": { + "description": "记录成功", + "schema": { + "$ref": "#/definitions/controller.Response" + } + } + } + } + }, + "/api/v1/pig-batches/{id}/sell-pigs": { + "post": { + "description": "记录猪批次中的猪只出售事件", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "猪批次管理" + ], + "summary": "处理卖猪的业务逻辑", + "parameters": [ + { + "type": "integer", + "description": "猪批次ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "卖猪请求信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SellPigsRequest" + } + } + ], + "responses": { + "200": { + "description": "卖猪成功", + "schema": { + "$ref": "#/definitions/controller.Response" + } + } + } + } + }, + "/api/v1/pig-batches/{id}/transfer-within-batch": { + "post": { + "description": "将指定数量的猪只在同一个猪群的不同猪栏间调动", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "猪批次管理" + ], + "summary": "群内调栏", + "parameters": [ + { + "type": "integer", + "description": "猪批次ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "群内调栏请求信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.TransferPigsWithinBatchRequest" + } + } + ], + "responses": { + "200": { + "description": "调栏成功", + "schema": { + "$ref": "#/definitions/controller.Response" + } + } + } + } + }, + "/api/v1/pig-batches/{sourceBatchID}/transfer-across-batches": { + "post": { + "description": "将指定数量的猪只从一个猪群的猪栏调动到另一个猪群的猪栏", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "猪批次管理" + ], + "summary": "跨猪群调栏", + "parameters": [ + { + "type": "integer", + "description": "源猪批次ID", + "name": "sourceBatchID", + "in": "path", + "required": true + }, + { + "description": "跨群调栏请求信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.TransferPigsAcrossBatchesRequest" + } + } + ], + "responses": { + "200": { + "description": "调栏成功", + "schema": { + "$ref": "#/definitions/controller.Response" + } + } + } + } + }, "/api/v1/pig-houses": { "get": { "description": "获取所有猪舍的列表", @@ -1930,6 +2340,50 @@ const docTemplate = `{ "dto.AssignEmptyPensToBatchRequest": { "type": "object" }, + "dto.BuyPigsRequest": { + "type": "object", + "required": [ + "penID", + "quantity", + "totalPrice", + "tradeDate", + "traderName", + "unitPrice" + ], + "properties": { + "penID": { + "description": "猪栏ID", + "type": "integer" + }, + "quantity": { + "description": "买入猪只数量", + "type": "integer", + "minimum": 1 + }, + "remarks": { + "description": "备注", + "type": "string" + }, + "totalPrice": { + "description": "总价", + "type": "number", + "minimum": 0 + }, + "tradeDate": { + "description": "交易日期", + "type": "string" + }, + "traderName": { + "description": "交易方名称", + "type": "string" + }, + "unitPrice": { + "description": "单价", + "type": "number", + "minimum": 0 + } + } + }, "dto.CreateAreaControllerRequest": { "type": "object", "required": [ @@ -2541,6 +2995,248 @@ const docTemplate = `{ } } }, + "dto.RecordCullRequest": { + "type": "object", + "required": [ + "happenedAt", + "penID", + "quantity" + ], + "properties": { + "happenedAt": { + "description": "发生时间", + "type": "string" + }, + "penID": { + "description": "猪栏ID", + "type": "integer" + }, + "quantity": { + "description": "淘汰猪数量", + "type": "integer", + "minimum": 1 + }, + "remarks": { + "description": "备注", + "type": "string" + } + } + }, + "dto.RecordDeathRequest": { + "type": "object", + "required": [ + "happenedAt", + "penID", + "quantity" + ], + "properties": { + "happenedAt": { + "description": "发生时间", + "type": "string" + }, + "penID": { + "description": "猪栏ID", + "type": "integer" + }, + "quantity": { + "description": "死亡猪数量", + "type": "integer", + "minimum": 1 + }, + "remarks": { + "description": "备注", + "type": "string" + } + } + }, + "dto.RecordSickPigCullRequest": { + "type": "object", + "required": [ + "happenedAt", + "penID", + "quantity", + "treatmentLocation" + ], + "properties": { + "happenedAt": { + "description": "发生时间", + "type": "string" + }, + "penID": { + "description": "猪栏ID", + "type": "integer" + }, + "quantity": { + "description": "淘汰猪数量", + "type": "integer", + "minimum": 1 + }, + "remarks": { + "description": "备注", + "type": "string" + }, + "treatmentLocation": { + "description": "治疗地点", + "allOf": [ + { + "$ref": "#/definitions/models.PigBatchSickPigTreatmentLocation" + } + ] + } + } + }, + "dto.RecordSickPigDeathRequest": { + "type": "object", + "required": [ + "happenedAt", + "penID", + "quantity", + "treatmentLocation" + ], + "properties": { + "happenedAt": { + "description": "发生时间", + "type": "string" + }, + "penID": { + "description": "猪栏ID", + "type": "integer" + }, + "quantity": { + "description": "死亡猪数量", + "type": "integer", + "minimum": 1 + }, + "remarks": { + "description": "备注", + "type": "string" + }, + "treatmentLocation": { + "description": "治疗地点", + "allOf": [ + { + "$ref": "#/definitions/models.PigBatchSickPigTreatmentLocation" + } + ] + } + } + }, + "dto.RecordSickPigRecoveryRequest": { + "type": "object", + "required": [ + "happenedAt", + "penID", + "quantity", + "treatmentLocation" + ], + "properties": { + "happenedAt": { + "description": "发生时间", + "type": "string" + }, + "penID": { + "description": "猪栏ID", + "type": "integer" + }, + "quantity": { + "description": "康复猪数量", + "type": "integer", + "minimum": 1 + }, + "remarks": { + "description": "备注", + "type": "string" + }, + "treatmentLocation": { + "description": "治疗地点", + "allOf": [ + { + "$ref": "#/definitions/models.PigBatchSickPigTreatmentLocation" + } + ] + } + } + }, + "dto.RecordSickPigsRequest": { + "type": "object", + "required": [ + "happenedAt", + "penID", + "quantity", + "treatmentLocation" + ], + "properties": { + "happenedAt": { + "description": "发生时间", + "type": "string" + }, + "penID": { + "description": "猪栏ID", + "type": "integer" + }, + "quantity": { + "description": "病猪数量", + "type": "integer", + "minimum": 1 + }, + "remarks": { + "description": "备注", + "type": "string" + }, + "treatmentLocation": { + "description": "治疗地点", + "allOf": [ + { + "$ref": "#/definitions/models.PigBatchSickPigTreatmentLocation" + } + ] + } + } + }, + "dto.SellPigsRequest": { + "type": "object", + "required": [ + "penID", + "quantity", + "totalPrice", + "tradeDate", + "traderName", + "unitPrice" + ], + "properties": { + "penID": { + "description": "猪栏ID", + "type": "integer" + }, + "quantity": { + "description": "卖出猪只数量", + "type": "integer", + "minimum": 1 + }, + "remarks": { + "description": "备注", + "type": "string" + }, + "totalPrice": { + "description": "总价", + "type": "number", + "minimum": 0 + }, + "tradeDate": { + "description": "交易日期", + "type": "string" + }, + "traderName": { + "description": "交易方名称", + "type": "string" + }, + "unitPrice": { + "description": "单价", + "type": "number", + "minimum": 0 + } + } + }, "dto.SubPlanResponse": { "type": "object", "properties": { @@ -2631,6 +3327,65 @@ const docTemplate = `{ } } }, + "dto.TransferPigsAcrossBatchesRequest": { + "type": "object", + "required": [ + "destBatchID", + "fromPenID", + "quantity", + "toPenID" + ], + "properties": { + "destBatchID": { + "description": "目标猪批次ID", + "type": "integer" + }, + "fromPenID": { + "description": "源猪栏ID", + "type": "integer" + }, + "quantity": { + "description": "调栏猪只数量", + "type": "integer", + "minimum": 1 + }, + "remarks": { + "description": "备注", + "type": "string" + }, + "toPenID": { + "description": "目标猪栏ID", + "type": "integer" + } + } + }, + "dto.TransferPigsWithinBatchRequest": { + "type": "object", + "required": [ + "fromPenID", + "quantity", + "toPenID" + ], + "properties": { + "fromPenID": { + "description": "源猪栏ID", + "type": "integer" + }, + "quantity": { + "description": "调栏猪只数量", + "type": "integer", + "minimum": 1 + }, + "remarks": { + "description": "备注", + "type": "string" + }, + "toPenID": { + "description": "目标猪栏ID", + "type": "integer" + } + } + }, "dto.UpdateAreaControllerRequest": { "type": "object", "required": [ @@ -2870,6 +3625,17 @@ const docTemplate = `{ "OriginTypePurchased" ] }, + "models.PigBatchSickPigTreatmentLocation": { + "type": "string", + "enum": [ + "原地治疗", + "病猪栏治疗" + ], + "x-enum-varnames": [ + "TreatmentLocationOnSite", + "TreatmentLocationSickBay" + ] + }, "models.PigBatchStatus": { "type": "string", "enum": [ diff --git a/docs/swagger.json b/docs/swagger.json index 3cad7f5..c14cfa3 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -856,7 +856,7 @@ "application/json" ], "tags": [ - "猪批次管理" + "猪群管理" ], "summary": "获取猪批次列表", "parameters": [ @@ -900,7 +900,7 @@ "application/json" ], "tags": [ - "猪批次管理" + "猪群管理" ], "summary": "创建猪批次", "parameters": [ @@ -943,7 +943,7 @@ "application/json" ], "tags": [ - "猪批次管理" + "猪群管理" ], "summary": "从猪批次移除空栏", "parameters": [ @@ -982,7 +982,7 @@ "application/json" ], "tags": [ - "猪批次管理" + "猪群管理" ], "summary": "将猪栏划拨到新批次", "parameters": [ @@ -1020,7 +1020,7 @@ "application/json" ], "tags": [ - "猪批次管理" + "猪群管理" ], "summary": "获取单个猪批次", "parameters": [ @@ -1062,7 +1062,7 @@ "application/json" ], "tags": [ - "猪批次管理" + "猪群管理" ], "summary": "更新猪批次", "parameters": [ @@ -1110,7 +1110,7 @@ "application/json" ], "tags": [ - "猪批次管理" + "猪群管理" ], "summary": "删除猪批次", "parameters": [ @@ -1142,7 +1142,7 @@ "application/json" ], "tags": [ - "猪批次管理" + "猪群管理" ], "summary": "为猪批次分配空栏", "parameters": [ @@ -1173,6 +1173,47 @@ } } }, + "/api/v1/pig-batches/{id}/buy-pigs": { + "post": { + "description": "记录猪批次中的猪只购买事件", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "猪批次管理" + ], + "summary": "处理买猪的业务逻辑", + "parameters": [ + { + "type": "integer", + "description": "猪批次ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "买猪请求信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.BuyPigsRequest" + } + } + ], + "responses": { + "200": { + "description": "买猪成功", + "schema": { + "$ref": "#/definitions/controller.Response" + } + } + } + } + }, "/api/v1/pig-batches/{id}/move-pigs-into-pen": { "post": { "description": "将指定数量的猪只从批次的“虚拟库存”移入一个已分配的猪栏", @@ -1183,7 +1224,7 @@ "application/json" ], "tags": [ - "猪批次管理" + "猪群管理" ], "summary": "将猪只从“虚拟库存”移入指定猪栏", "parameters": [ @@ -1214,6 +1255,375 @@ } } }, + "/api/v1/pig-batches/{id}/record-cull": { + "post": { + "description": "记录猪批次中正常猪只淘汰的数量和发生时间", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "猪批次管理" + ], + "summary": "记录正常猪只淘汰事件", + "parameters": [ + { + "type": "integer", + "description": "猪批次ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "记录正常猪只淘汰请求信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.RecordCullRequest" + } + } + ], + "responses": { + "200": { + "description": "记录成功", + "schema": { + "$ref": "#/definitions/controller.Response" + } + } + } + } + }, + "/api/v1/pig-batches/{id}/record-death": { + "post": { + "description": "记录猪批次中正常猪只死亡的数量和发生时间", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "猪批次管理" + ], + "summary": "记录正常猪只死亡事件", + "parameters": [ + { + "type": "integer", + "description": "猪批次ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "记录正常猪只死亡请求信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.RecordDeathRequest" + } + } + ], + "responses": { + "200": { + "description": "记录成功", + "schema": { + "$ref": "#/definitions/controller.Response" + } + } + } + } + }, + "/api/v1/pig-batches/{id}/record-sick-pig-cull": { + "post": { + "description": "记录猪批次中病猪淘汰的数量、治疗地点和发生时间", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "猪批次管理" + ], + "summary": "记录病猪淘汰事件", + "parameters": [ + { + "type": "integer", + "description": "猪批次ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "记录病猪淘汰请求信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.RecordSickPigCullRequest" + } + } + ], + "responses": { + "200": { + "description": "记录成功", + "schema": { + "$ref": "#/definitions/controller.Response" + } + } + } + } + }, + "/api/v1/pig-batches/{id}/record-sick-pig-death": { + "post": { + "description": "记录猪批次中病猪死亡的数量、治疗地点和发生时间", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "猪批次管理" + ], + "summary": "记录病猪死亡事件", + "parameters": [ + { + "type": "integer", + "description": "猪批次ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "记录病猪死亡请求信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.RecordSickPigDeathRequest" + } + } + ], + "responses": { + "200": { + "description": "记录成功", + "schema": { + "$ref": "#/definitions/controller.Response" + } + } + } + } + }, + "/api/v1/pig-batches/{id}/record-sick-pig-recovery": { + "post": { + "description": "记录猪批次中病猪康复的数量、治疗地点和发生时间", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "猪批次管理" + ], + "summary": "记录病猪康复事件", + "parameters": [ + { + "type": "integer", + "description": "猪批次ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "记录病猪康复请求信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.RecordSickPigRecoveryRequest" + } + } + ], + "responses": { + "200": { + "description": "记录成功", + "schema": { + "$ref": "#/definitions/controller.Response" + } + } + } + } + }, + "/api/v1/pig-batches/{id}/record-sick-pigs": { + "post": { + "description": "记录猪批次中新增病猪的数量、治疗地点和发生时间", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "猪批次管理" + ], + "summary": "记录新增病猪事件", + "parameters": [ + { + "type": "integer", + "description": "猪批次ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "记录病猪请求信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.RecordSickPigsRequest" + } + } + ], + "responses": { + "200": { + "description": "记录成功", + "schema": { + "$ref": "#/definitions/controller.Response" + } + } + } + } + }, + "/api/v1/pig-batches/{id}/sell-pigs": { + "post": { + "description": "记录猪批次中的猪只出售事件", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "猪批次管理" + ], + "summary": "处理卖猪的业务逻辑", + "parameters": [ + { + "type": "integer", + "description": "猪批次ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "卖猪请求信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SellPigsRequest" + } + } + ], + "responses": { + "200": { + "description": "卖猪成功", + "schema": { + "$ref": "#/definitions/controller.Response" + } + } + } + } + }, + "/api/v1/pig-batches/{id}/transfer-within-batch": { + "post": { + "description": "将指定数量的猪只在同一个猪群的不同猪栏间调动", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "猪批次管理" + ], + "summary": "群内调栏", + "parameters": [ + { + "type": "integer", + "description": "猪批次ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "群内调栏请求信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.TransferPigsWithinBatchRequest" + } + } + ], + "responses": { + "200": { + "description": "调栏成功", + "schema": { + "$ref": "#/definitions/controller.Response" + } + } + } + } + }, + "/api/v1/pig-batches/{sourceBatchID}/transfer-across-batches": { + "post": { + "description": "将指定数量的猪只从一个猪群的猪栏调动到另一个猪群的猪栏", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "猪批次管理" + ], + "summary": "跨猪群调栏", + "parameters": [ + { + "type": "integer", + "description": "源猪批次ID", + "name": "sourceBatchID", + "in": "path", + "required": true + }, + { + "description": "跨群调栏请求信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.TransferPigsAcrossBatchesRequest" + } + } + ], + "responses": { + "200": { + "description": "调栏成功", + "schema": { + "$ref": "#/definitions/controller.Response" + } + } + } + } + }, "/api/v1/pig-houses": { "get": { "description": "获取所有猪舍的列表", @@ -1919,6 +2329,50 @@ "dto.AssignEmptyPensToBatchRequest": { "type": "object" }, + "dto.BuyPigsRequest": { + "type": "object", + "required": [ + "penID", + "quantity", + "totalPrice", + "tradeDate", + "traderName", + "unitPrice" + ], + "properties": { + "penID": { + "description": "猪栏ID", + "type": "integer" + }, + "quantity": { + "description": "买入猪只数量", + "type": "integer", + "minimum": 1 + }, + "remarks": { + "description": "备注", + "type": "string" + }, + "totalPrice": { + "description": "总价", + "type": "number", + "minimum": 0 + }, + "tradeDate": { + "description": "交易日期", + "type": "string" + }, + "traderName": { + "description": "交易方名称", + "type": "string" + }, + "unitPrice": { + "description": "单价", + "type": "number", + "minimum": 0 + } + } + }, "dto.CreateAreaControllerRequest": { "type": "object", "required": [ @@ -2530,6 +2984,248 @@ } } }, + "dto.RecordCullRequest": { + "type": "object", + "required": [ + "happenedAt", + "penID", + "quantity" + ], + "properties": { + "happenedAt": { + "description": "发生时间", + "type": "string" + }, + "penID": { + "description": "猪栏ID", + "type": "integer" + }, + "quantity": { + "description": "淘汰猪数量", + "type": "integer", + "minimum": 1 + }, + "remarks": { + "description": "备注", + "type": "string" + } + } + }, + "dto.RecordDeathRequest": { + "type": "object", + "required": [ + "happenedAt", + "penID", + "quantity" + ], + "properties": { + "happenedAt": { + "description": "发生时间", + "type": "string" + }, + "penID": { + "description": "猪栏ID", + "type": "integer" + }, + "quantity": { + "description": "死亡猪数量", + "type": "integer", + "minimum": 1 + }, + "remarks": { + "description": "备注", + "type": "string" + } + } + }, + "dto.RecordSickPigCullRequest": { + "type": "object", + "required": [ + "happenedAt", + "penID", + "quantity", + "treatmentLocation" + ], + "properties": { + "happenedAt": { + "description": "发生时间", + "type": "string" + }, + "penID": { + "description": "猪栏ID", + "type": "integer" + }, + "quantity": { + "description": "淘汰猪数量", + "type": "integer", + "minimum": 1 + }, + "remarks": { + "description": "备注", + "type": "string" + }, + "treatmentLocation": { + "description": "治疗地点", + "allOf": [ + { + "$ref": "#/definitions/models.PigBatchSickPigTreatmentLocation" + } + ] + } + } + }, + "dto.RecordSickPigDeathRequest": { + "type": "object", + "required": [ + "happenedAt", + "penID", + "quantity", + "treatmentLocation" + ], + "properties": { + "happenedAt": { + "description": "发生时间", + "type": "string" + }, + "penID": { + "description": "猪栏ID", + "type": "integer" + }, + "quantity": { + "description": "死亡猪数量", + "type": "integer", + "minimum": 1 + }, + "remarks": { + "description": "备注", + "type": "string" + }, + "treatmentLocation": { + "description": "治疗地点", + "allOf": [ + { + "$ref": "#/definitions/models.PigBatchSickPigTreatmentLocation" + } + ] + } + } + }, + "dto.RecordSickPigRecoveryRequest": { + "type": "object", + "required": [ + "happenedAt", + "penID", + "quantity", + "treatmentLocation" + ], + "properties": { + "happenedAt": { + "description": "发生时间", + "type": "string" + }, + "penID": { + "description": "猪栏ID", + "type": "integer" + }, + "quantity": { + "description": "康复猪数量", + "type": "integer", + "minimum": 1 + }, + "remarks": { + "description": "备注", + "type": "string" + }, + "treatmentLocation": { + "description": "治疗地点", + "allOf": [ + { + "$ref": "#/definitions/models.PigBatchSickPigTreatmentLocation" + } + ] + } + } + }, + "dto.RecordSickPigsRequest": { + "type": "object", + "required": [ + "happenedAt", + "penID", + "quantity", + "treatmentLocation" + ], + "properties": { + "happenedAt": { + "description": "发生时间", + "type": "string" + }, + "penID": { + "description": "猪栏ID", + "type": "integer" + }, + "quantity": { + "description": "病猪数量", + "type": "integer", + "minimum": 1 + }, + "remarks": { + "description": "备注", + "type": "string" + }, + "treatmentLocation": { + "description": "治疗地点", + "allOf": [ + { + "$ref": "#/definitions/models.PigBatchSickPigTreatmentLocation" + } + ] + } + } + }, + "dto.SellPigsRequest": { + "type": "object", + "required": [ + "penID", + "quantity", + "totalPrice", + "tradeDate", + "traderName", + "unitPrice" + ], + "properties": { + "penID": { + "description": "猪栏ID", + "type": "integer" + }, + "quantity": { + "description": "卖出猪只数量", + "type": "integer", + "minimum": 1 + }, + "remarks": { + "description": "备注", + "type": "string" + }, + "totalPrice": { + "description": "总价", + "type": "number", + "minimum": 0 + }, + "tradeDate": { + "description": "交易日期", + "type": "string" + }, + "traderName": { + "description": "交易方名称", + "type": "string" + }, + "unitPrice": { + "description": "单价", + "type": "number", + "minimum": 0 + } + } + }, "dto.SubPlanResponse": { "type": "object", "properties": { @@ -2620,6 +3316,65 @@ } } }, + "dto.TransferPigsAcrossBatchesRequest": { + "type": "object", + "required": [ + "destBatchID", + "fromPenID", + "quantity", + "toPenID" + ], + "properties": { + "destBatchID": { + "description": "目标猪批次ID", + "type": "integer" + }, + "fromPenID": { + "description": "源猪栏ID", + "type": "integer" + }, + "quantity": { + "description": "调栏猪只数量", + "type": "integer", + "minimum": 1 + }, + "remarks": { + "description": "备注", + "type": "string" + }, + "toPenID": { + "description": "目标猪栏ID", + "type": "integer" + } + } + }, + "dto.TransferPigsWithinBatchRequest": { + "type": "object", + "required": [ + "fromPenID", + "quantity", + "toPenID" + ], + "properties": { + "fromPenID": { + "description": "源猪栏ID", + "type": "integer" + }, + "quantity": { + "description": "调栏猪只数量", + "type": "integer", + "minimum": 1 + }, + "remarks": { + "description": "备注", + "type": "string" + }, + "toPenID": { + "description": "目标猪栏ID", + "type": "integer" + } + } + }, "dto.UpdateAreaControllerRequest": { "type": "object", "required": [ @@ -2859,6 +3614,17 @@ "OriginTypePurchased" ] }, + "models.PigBatchSickPigTreatmentLocation": { + "type": "string", + "enum": [ + "原地治疗", + "病猪栏治疗" + ], + "x-enum-varnames": [ + "TreatmentLocationOnSite", + "TreatmentLocationSickBay" + ] + }, "models.PigBatchStatus": { "type": "string", "enum": [ diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 65a1b65..e5dcd7c 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -71,6 +71,40 @@ definitions: type: object dto.AssignEmptyPensToBatchRequest: type: object + dto.BuyPigsRequest: + properties: + penID: + description: 猪栏ID + type: integer + quantity: + description: 买入猪只数量 + minimum: 1 + type: integer + remarks: + description: 备注 + type: string + totalPrice: + description: 总价 + minimum: 0 + type: number + tradeDate: + description: 交易日期 + type: string + traderName: + description: 交易方名称 + type: string + unitPrice: + description: 单价 + minimum: 0 + type: number + required: + - penID + - quantity + - totalPrice + - tradeDate + - traderName + - unitPrice + type: object dto.CreateAreaControllerRequest: properties: location: @@ -481,6 +515,180 @@ definitions: - penID - toBatchID type: object + dto.RecordCullRequest: + properties: + happenedAt: + description: 发生时间 + type: string + penID: + description: 猪栏ID + type: integer + quantity: + description: 淘汰猪数量 + minimum: 1 + type: integer + remarks: + description: 备注 + type: string + required: + - happenedAt + - penID + - quantity + type: object + dto.RecordDeathRequest: + properties: + happenedAt: + description: 发生时间 + type: string + penID: + description: 猪栏ID + type: integer + quantity: + description: 死亡猪数量 + minimum: 1 + type: integer + remarks: + description: 备注 + type: string + required: + - happenedAt + - penID + - quantity + type: object + dto.RecordSickPigCullRequest: + properties: + happenedAt: + description: 发生时间 + type: string + penID: + description: 猪栏ID + type: integer + quantity: + description: 淘汰猪数量 + minimum: 1 + type: integer + remarks: + description: 备注 + type: string + treatmentLocation: + allOf: + - $ref: '#/definitions/models.PigBatchSickPigTreatmentLocation' + description: 治疗地点 + required: + - happenedAt + - penID + - quantity + - treatmentLocation + type: object + dto.RecordSickPigDeathRequest: + properties: + happenedAt: + description: 发生时间 + type: string + penID: + description: 猪栏ID + type: integer + quantity: + description: 死亡猪数量 + minimum: 1 + type: integer + remarks: + description: 备注 + type: string + treatmentLocation: + allOf: + - $ref: '#/definitions/models.PigBatchSickPigTreatmentLocation' + description: 治疗地点 + required: + - happenedAt + - penID + - quantity + - treatmentLocation + type: object + dto.RecordSickPigRecoveryRequest: + properties: + happenedAt: + description: 发生时间 + type: string + penID: + description: 猪栏ID + type: integer + quantity: + description: 康复猪数量 + minimum: 1 + type: integer + remarks: + description: 备注 + type: string + treatmentLocation: + allOf: + - $ref: '#/definitions/models.PigBatchSickPigTreatmentLocation' + description: 治疗地点 + required: + - happenedAt + - penID + - quantity + - treatmentLocation + type: object + dto.RecordSickPigsRequest: + properties: + happenedAt: + description: 发生时间 + type: string + penID: + description: 猪栏ID + type: integer + quantity: + description: 病猪数量 + minimum: 1 + type: integer + remarks: + description: 备注 + type: string + treatmentLocation: + allOf: + - $ref: '#/definitions/models.PigBatchSickPigTreatmentLocation' + description: 治疗地点 + required: + - happenedAt + - penID + - quantity + - treatmentLocation + type: object + dto.SellPigsRequest: + properties: + penID: + description: 猪栏ID + type: integer + quantity: + description: 卖出猪只数量 + minimum: 1 + type: integer + remarks: + description: 备注 + type: string + totalPrice: + description: 总价 + minimum: 0 + type: number + tradeDate: + description: 交易日期 + type: string + traderName: + description: 交易方名称 + type: string + unitPrice: + description: 单价 + minimum: 0 + type: number + required: + - penID + - quantity + - totalPrice + - tradeDate + - traderName + - unitPrice + type: object dto.SubPlanResponse: properties: child_plan: @@ -542,6 +750,50 @@ definitions: - $ref: '#/definitions/models.TaskType' example: 等待 type: object + dto.TransferPigsAcrossBatchesRequest: + properties: + destBatchID: + description: 目标猪批次ID + type: integer + fromPenID: + description: 源猪栏ID + type: integer + quantity: + description: 调栏猪只数量 + minimum: 1 + type: integer + remarks: + description: 备注 + type: string + toPenID: + description: 目标猪栏ID + type: integer + required: + - destBatchID + - fromPenID + - quantity + - toPenID + type: object + dto.TransferPigsWithinBatchRequest: + properties: + fromPenID: + description: 源猪栏ID + type: integer + quantity: + description: 调栏猪只数量 + minimum: 1 + type: integer + remarks: + description: 备注 + type: string + toPenID: + description: 目标猪栏ID + type: integer + required: + - fromPenID + - quantity + - toPenID + type: object dto.UpdateAreaControllerRequest: properties: location: @@ -708,6 +960,14 @@ definitions: x-enum-varnames: - OriginTypeSelfFarrowed - OriginTypePurchased + models.PigBatchSickPigTreatmentLocation: + enum: + - 原地治疗 + - 病猪栏治疗 + type: string + x-enum-varnames: + - TreatmentLocationOnSite + - TreatmentLocationSickBay models.PigBatchStatus: enum: - 保育 @@ -1377,7 +1637,7 @@ paths: type: object summary: 获取猪批次列表 tags: - - 猪批次管理 + - 猪群管理 post: consumes: - application/json @@ -1403,7 +1663,7 @@ paths: type: object summary: 创建猪批次 tags: - - 猪批次管理 + - 猪群管理 /api/v1/pig-batches/{batchID}/remove-pen/{penID}: delete: description: 将一个空闲猪栏从指定的猪批次中移除 @@ -1427,7 +1687,7 @@ paths: $ref: '#/definitions/controller.Response' summary: 从猪批次移除空栏 tags: - - 猪批次管理 + - 猪群管理 /api/v1/pig-batches/{fromBatchID}/reclassify-pen: post: consumes: @@ -1454,7 +1714,7 @@ paths: $ref: '#/definitions/controller.Response' summary: 将猪栏划拨到新批次 tags: - - 猪批次管理 + - 猪群管理 /api/v1/pig-batches/{id}: delete: description: 根据ID删除一个猪批次 @@ -1473,7 +1733,7 @@ paths: $ref: '#/definitions/controller.Response' summary: 删除猪批次 tags: - - 猪批次管理 + - 猪群管理 get: description: 根据ID获取单个猪批次信息 parameters: @@ -1496,7 +1756,7 @@ paths: type: object summary: 获取单个猪批次 tags: - - 猪批次管理 + - 猪群管理 put: consumes: - application/json @@ -1527,7 +1787,7 @@ paths: type: object summary: 更新猪批次 tags: - - 猪批次管理 + - 猪群管理 /api/v1/pig-batches/{id}/assign-pens: post: consumes: @@ -1554,6 +1814,33 @@ paths: $ref: '#/definitions/controller.Response' summary: 为猪批次分配空栏 tags: + - 猪群管理 + /api/v1/pig-batches/{id}/buy-pigs: + post: + consumes: + - application/json + description: 记录猪批次中的猪只购买事件 + parameters: + - description: 猪批次ID + in: path + name: id + required: true + type: integer + - description: 买猪请求信息 + in: body + name: body + required: true + schema: + $ref: '#/definitions/dto.BuyPigsRequest' + produces: + - application/json + responses: + "200": + description: 买猪成功 + schema: + $ref: '#/definitions/controller.Response' + summary: 处理买猪的业务逻辑 + tags: - 猪批次管理 /api/v1/pig-batches/{id}/move-pigs-into-pen: post: @@ -1581,6 +1868,249 @@ paths: $ref: '#/definitions/controller.Response' summary: 将猪只从“虚拟库存”移入指定猪栏 tags: + - 猪群管理 + /api/v1/pig-batches/{id}/record-cull: + post: + consumes: + - application/json + description: 记录猪批次中正常猪只淘汰的数量和发生时间 + parameters: + - description: 猪批次ID + in: path + name: id + required: true + type: integer + - description: 记录正常猪只淘汰请求信息 + in: body + name: body + required: true + schema: + $ref: '#/definitions/dto.RecordCullRequest' + produces: + - application/json + responses: + "200": + description: 记录成功 + schema: + $ref: '#/definitions/controller.Response' + summary: 记录正常猪只淘汰事件 + tags: + - 猪批次管理 + /api/v1/pig-batches/{id}/record-death: + post: + consumes: + - application/json + description: 记录猪批次中正常猪只死亡的数量和发生时间 + parameters: + - description: 猪批次ID + in: path + name: id + required: true + type: integer + - description: 记录正常猪只死亡请求信息 + in: body + name: body + required: true + schema: + $ref: '#/definitions/dto.RecordDeathRequest' + produces: + - application/json + responses: + "200": + description: 记录成功 + schema: + $ref: '#/definitions/controller.Response' + summary: 记录正常猪只死亡事件 + tags: + - 猪批次管理 + /api/v1/pig-batches/{id}/record-sick-pig-cull: + post: + consumes: + - application/json + description: 记录猪批次中病猪淘汰的数量、治疗地点和发生时间 + parameters: + - description: 猪批次ID + in: path + name: id + required: true + type: integer + - description: 记录病猪淘汰请求信息 + in: body + name: body + required: true + schema: + $ref: '#/definitions/dto.RecordSickPigCullRequest' + produces: + - application/json + responses: + "200": + description: 记录成功 + schema: + $ref: '#/definitions/controller.Response' + summary: 记录病猪淘汰事件 + tags: + - 猪批次管理 + /api/v1/pig-batches/{id}/record-sick-pig-death: + post: + consumes: + - application/json + description: 记录猪批次中病猪死亡的数量、治疗地点和发生时间 + parameters: + - description: 猪批次ID + in: path + name: id + required: true + type: integer + - description: 记录病猪死亡请求信息 + in: body + name: body + required: true + schema: + $ref: '#/definitions/dto.RecordSickPigDeathRequest' + produces: + - application/json + responses: + "200": + description: 记录成功 + schema: + $ref: '#/definitions/controller.Response' + summary: 记录病猪死亡事件 + tags: + - 猪批次管理 + /api/v1/pig-batches/{id}/record-sick-pig-recovery: + post: + consumes: + - application/json + description: 记录猪批次中病猪康复的数量、治疗地点和发生时间 + parameters: + - description: 猪批次ID + in: path + name: id + required: true + type: integer + - description: 记录病猪康复请求信息 + in: body + name: body + required: true + schema: + $ref: '#/definitions/dto.RecordSickPigRecoveryRequest' + produces: + - application/json + responses: + "200": + description: 记录成功 + schema: + $ref: '#/definitions/controller.Response' + summary: 记录病猪康复事件 + tags: + - 猪批次管理 + /api/v1/pig-batches/{id}/record-sick-pigs: + post: + consumes: + - application/json + description: 记录猪批次中新增病猪的数量、治疗地点和发生时间 + parameters: + - description: 猪批次ID + in: path + name: id + required: true + type: integer + - description: 记录病猪请求信息 + in: body + name: body + required: true + schema: + $ref: '#/definitions/dto.RecordSickPigsRequest' + produces: + - application/json + responses: + "200": + description: 记录成功 + schema: + $ref: '#/definitions/controller.Response' + summary: 记录新增病猪事件 + tags: + - 猪批次管理 + /api/v1/pig-batches/{id}/sell-pigs: + post: + consumes: + - application/json + description: 记录猪批次中的猪只出售事件 + parameters: + - description: 猪批次ID + in: path + name: id + required: true + type: integer + - description: 卖猪请求信息 + in: body + name: body + required: true + schema: + $ref: '#/definitions/dto.SellPigsRequest' + produces: + - application/json + responses: + "200": + description: 卖猪成功 + schema: + $ref: '#/definitions/controller.Response' + summary: 处理卖猪的业务逻辑 + tags: + - 猪批次管理 + /api/v1/pig-batches/{id}/transfer-within-batch: + post: + consumes: + - application/json + description: 将指定数量的猪只在同一个猪群的不同猪栏间调动 + parameters: + - description: 猪批次ID + in: path + name: id + required: true + type: integer + - description: 群内调栏请求信息 + in: body + name: body + required: true + schema: + $ref: '#/definitions/dto.TransferPigsWithinBatchRequest' + produces: + - application/json + responses: + "200": + description: 调栏成功 + schema: + $ref: '#/definitions/controller.Response' + summary: 群内调栏 + tags: + - 猪批次管理 + /api/v1/pig-batches/{sourceBatchID}/transfer-across-batches: + post: + consumes: + - application/json + description: 将指定数量的猪只从一个猪群的猪栏调动到另一个猪群的猪栏 + parameters: + - description: 源猪批次ID + in: path + name: sourceBatchID + required: true + type: integer + - description: 跨群调栏请求信息 + in: body + name: body + required: true + schema: + $ref: '#/definitions/dto.TransferPigsAcrossBatchesRequest' + produces: + - application/json + responses: + "200": + description: 调栏成功 + schema: + $ref: '#/definitions/controller.Response' + summary: 跨猪群调栏 + tags: - 猪批次管理 /api/v1/pig-houses: get: diff --git a/internal/app/api/api.go b/internal/app/api/api.go index 745a036..56aa248 100644 --- a/internal/app/api/api.go +++ b/internal/app/api/api.go @@ -226,7 +226,7 @@ func (a *API) setupRoutes() { } a.logger.Info("猪圈相关接口注册成功 (需要认证和审计)") - // 猪批次相关路由组 + // 猪群相关路由组 pigBatchGroup := authGroup.Group("/pig-batches") { pigBatchGroup.POST("", a.pigBatchController.CreatePigBatch) @@ -238,6 +238,16 @@ func (a *API) setupRoutes() { pigBatchGroup.POST("/:fromBatchID/reclassify-pen", a.pigBatchController.ReclassifyPenToNewBatch) pigBatchGroup.DELETE("/:batchID/remove-pen/:penID", a.pigBatchController.RemoveEmptyPenFromBatch) pigBatchGroup.POST("/:id/move-pigs-into-pen", a.pigBatchController.MovePigsIntoPen) + pigBatchGroup.POST("/:id/sell-pigs", a.pigBatchController.SellPigs) + pigBatchGroup.POST("/:id/buy-pigs", a.pigBatchController.BuyPigs) + pigBatchGroup.POST("/:sourceBatchID/transfer-across-batches", a.pigBatchController.TransferPigsAcrossBatches) + pigBatchGroup.POST("/:id/transfer-within-batch", a.pigBatchController.TransferPigsWithinBatch) + pigBatchGroup.POST("/:id/record-sick-pigs", a.pigBatchController.RecordSickPigs) + pigBatchGroup.POST("/:id/record-sick-pig-recovery", a.pigBatchController.RecordSickPigRecovery) + pigBatchGroup.POST("/:id/record-sick-pig-death", a.pigBatchController.RecordSickPigDeath) + pigBatchGroup.POST("/:id/record-sick-pig-cull", a.pigBatchController.RecordSickPigCull) + pigBatchGroup.POST("/:id/record-death", a.pigBatchController.RecordDeath) + pigBatchGroup.POST("/:id/record-cull", a.pigBatchController.RecordCull) } a.logger.Info("猪批次相关接口注册成功 (需要认证和审计)") diff --git a/internal/app/controller/management/pig_batch_controller.go b/internal/app/controller/management/pig_batch_controller.go index 45d7e00..623d680 100644 --- a/internal/app/controller/management/pig_batch_controller.go +++ b/internal/app/controller/management/pig_batch_controller.go @@ -29,7 +29,7 @@ func NewPigBatchController(logger *logs.Logger, service service.PigBatchService) // CreatePigBatch godoc // @Summary 创建猪批次 // @Description 创建一个新的猪批次 -// @Tags 猪批次管理 +// @Tags 猪群管理 // @Accept json // @Produce json // @Param body body dto.PigBatchCreateDTO true "猪批次信息" @@ -58,7 +58,7 @@ func (c *PigBatchController) CreatePigBatch(ctx *gin.Context) { // GetPigBatch godoc // @Summary 获取单个猪批次 // @Description 根据ID获取单个猪批次信息 -// @Tags 猪批次管理 +// @Tags 猪群管理 // @Produce json // @Param id path int true "猪批次ID" // @Success 200 {object} controller.Response{data=dto.PigBatchResponseDTO} "获取成功" @@ -88,7 +88,7 @@ func (c *PigBatchController) GetPigBatch(ctx *gin.Context) { // UpdatePigBatch godoc // @Summary 更新猪批次 // @Description 更新一个已存在的猪批次信息 -// @Tags 猪批次管理 +// @Tags 猪群管理 // @Accept json // @Produce json // @Param id path int true "猪批次ID" @@ -126,7 +126,7 @@ func (c *PigBatchController) UpdatePigBatch(ctx *gin.Context) { // DeletePigBatch godoc // @Summary 删除猪批次 // @Description 根据ID删除一个猪批次 -// @Tags 猪批次管理 +// @Tags 猪群管理 // @Produce json // @Param id path int true "猪批次ID" // @Success 200 {object} controller.Response "删除成功" @@ -155,7 +155,7 @@ func (c *PigBatchController) DeletePigBatch(ctx *gin.Context) { // ListPigBatches godoc // @Summary 获取猪批次列表 // @Description 获取所有猪批次的列表,支持按活跃状态筛选 -// @Tags 猪批次管理 +// @Tags 猪群管理 // @Produce json // @Param is_active query bool false "是否活跃 (true/false)" // @Success 200 {object} controller.Response{data=[]dto.PigBatchResponseDTO} "获取成功" @@ -182,7 +182,7 @@ func (c *PigBatchController) ListPigBatches(ctx *gin.Context) { // AssignEmptyPensToBatch godoc // @Summary 为猪批次分配空栏 // @Description 将一个或多个空闲猪栏分配给指定的猪批次 -// @Tags 猪批次管理 +// @Tags 猪群管理 // @Accept json // @Produce json // @Param id path int true "猪批次ID" @@ -225,7 +225,7 @@ func (c *PigBatchController) AssignEmptyPensToBatch(ctx *gin.Context) { // ReclassifyPenToNewBatch godoc // @Summary 将猪栏划拨到新批次 // @Description 将一个猪栏(连同其中的猪只)从一个批次整体划拨到另一个批次 -// @Tags 猪批次管理 +// @Tags 猪群管理 // @Accept json // @Produce json // @Param fromBatchID path int true "源猪批次ID" @@ -268,7 +268,7 @@ func (c *PigBatchController) ReclassifyPenToNewBatch(ctx *gin.Context) { // RemoveEmptyPenFromBatch godoc // @Summary 从猪批次移除空栏 // @Description 将一个空闲猪栏从指定的猪批次中移除 -// @Tags 猪批次管理 +// @Tags 猪群管理 // @Produce json // @Param batchID path int true "猪批次ID" // @Param penID path int true "待移除的猪栏ID" @@ -308,7 +308,7 @@ func (c *PigBatchController) RemoveEmptyPenFromBatch(ctx *gin.Context) { // MovePigsIntoPen godoc // @Summary 将猪只从“虚拟库存”移入指定猪栏 // @Description 将指定数量的猪只从批次的“虚拟库存”移入一个已分配的猪栏 -// @Tags 猪批次管理 +// @Tags 猪群管理 // @Accept json // @Produce json // @Param id path int true "猪批次ID" diff --git a/internal/app/controller/management/pig_batch_health_controller.go b/internal/app/controller/management/pig_batch_health_controller.go new file mode 100644 index 0000000..3b4c09f --- /dev/null +++ b/internal/app/controller/management/pig_batch_health_controller.go @@ -0,0 +1,269 @@ +package management + +import ( + "errors" + "strconv" + + "git.huangwc.com/pig/pig-farm-controller/internal/app/controller" + "git.huangwc.com/pig/pig-farm-controller/internal/app/dto" + "git.huangwc.com/pig/pig-farm-controller/internal/app/service" + "github.com/gin-gonic/gin" +) + +// RecordSickPigs godoc +// @Summary 记录新增病猪事件 +// @Description 记录猪批次中新增病猪的数量、治疗地点和发生时间 +// @Tags 猪批次管理 +// @Accept json +// @Produce json +// @Param id path int true "猪批次ID" +// @Param body body dto.RecordSickPigsRequest true "记录病猪请求信息" +// @Success 200 {object} controller.Response "记录成功" +// @Router /api/v1/pig-batches/{id}/record-sick-pigs [post] +func (c *PigBatchController) RecordSickPigs(ctx *gin.Context) { + const action = "记录新增病猪事件" + batchID, err := strconv.ParseUint(ctx.Param("id"), 10, 32) + if err != nil { + controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的猪批次ID格式", action, "ID格式错误", ctx.Param("id")) + return + } + + var req dto.RecordSickPigsRequest + if err := ctx.ShouldBindJSON(&req); err != nil { + controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req) + return + } + + operatorID, err := controller.GetOperatorIDFromContext(ctx) + + err = c.service.RecordSickPigs(operatorID, uint(batchID), req.PenID, req.Quantity, req.TreatmentLocation, req.HappenedAt, req.Remarks) + if err != nil { + if errors.Is(err, service.ErrPigBatchNotFound) || errors.Is(err, service.ErrPenNotFound) { + controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), action, err.Error(), batchID) + return + } else if errors.Is(err, service.ErrInvalidOperation) || errors.Is(err, service.ErrPigBatchNotActive) || errors.Is(err, service.ErrPenNotAssociatedWithBatch) || errors.Is(err, service.ErrPenNotEmpty) { + controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), action, err.Error(), batchID) + return + } + c.logger.Errorf("%s: 业务逻辑失败: %v", action, err) + controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "记录新增病猪事件失败", action, err.Error(), batchID) + return + } + + controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "记录成功", nil, action, "记录成功", batchID) +} + +// RecordSickPigRecovery godoc +// @Summary 记录病猪康复事件 +// @Description 记录猪批次中病猪康复的数量、治疗地点和发生时间 +// @Tags 猪批次管理 +// @Accept json +// @Produce json +// @Param id path int true "猪批次ID" +// @Param body body dto.RecordSickPigRecoveryRequest true "记录病猪康复请求信息" +// @Success 200 {object} controller.Response "记录成功" +// @Router /api/v1/pig-batches/{id}/record-sick-pig-recovery [post] +func (c *PigBatchController) RecordSickPigRecovery(ctx *gin.Context) { + const action = "记录病猪康复事件" + batchID, err := strconv.ParseUint(ctx.Param("id"), 10, 32) + if err != nil { + controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的猪批次ID格式", action, "ID格式错误", ctx.Param("id")) + return + } + + var req dto.RecordSickPigRecoveryRequest + if err := ctx.ShouldBindJSON(&req); err != nil { + controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req) + return + } + + operatorID, err := controller.GetOperatorIDFromContext(ctx) + + err = c.service.RecordSickPigRecovery(operatorID, uint(batchID), req.PenID, req.Quantity, req.TreatmentLocation, req.HappenedAt, req.Remarks) + if err != nil { + if errors.Is(err, service.ErrPigBatchNotFound) || errors.Is(err, service.ErrPenNotFound) { + controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), action, err.Error(), batchID) + return + } else if errors.Is(err, service.ErrInvalidOperation) || errors.Is(err, service.ErrPigBatchNotActive) || errors.Is(err, service.ErrPenNotAssociatedWithBatch) || errors.Is(err, service.ErrPenNotEmpty) { + controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), action, err.Error(), batchID) + return + } + c.logger.Errorf("%s: 业务逻辑失败: %v", action, err) + controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "记录病猪康复事件失败", action, err.Error(), batchID) + return + } + + controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "记录成功", nil, action, "记录成功", batchID) +} + +// RecordSickPigDeath godoc +// @Summary 记录病猪死亡事件 +// @Description 记录猪批次中病猪死亡的数量、治疗地点和发生时间 +// @Tags 猪批次管理 +// @Accept json +// @Produce json +// @Param id path int true "猪批次ID" +// @Param body body dto.RecordSickPigDeathRequest true "记录病猪死亡请求信息" +// @Success 200 {object} controller.Response "记录成功" +// @Router /api/v1/pig-batches/{id}/record-sick-pig-death [post] +func (c *PigBatchController) RecordSickPigDeath(ctx *gin.Context) { + const action = "记录病猪死亡事件" + batchID, err := strconv.ParseUint(ctx.Param("id"), 10, 32) + if err != nil { + controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的猪批次ID格式", action, "ID格式错误", ctx.Param("id")) + return + } + + var req dto.RecordSickPigDeathRequest + if err := ctx.ShouldBindJSON(&req); err != nil { + controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req) + return + } + + operatorID, err := controller.GetOperatorIDFromContext(ctx) + + err = c.service.RecordSickPigDeath(operatorID, uint(batchID), req.PenID, req.Quantity, req.TreatmentLocation, req.HappenedAt, req.Remarks) + if err != nil { + if errors.Is(err, service.ErrPigBatchNotFound) || errors.Is(err, service.ErrPenNotFound) { + controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), action, err.Error(), batchID) + return + } else if errors.Is(err, service.ErrInvalidOperation) || errors.Is(err, service.ErrPigBatchNotActive) || errors.Is(err, service.ErrPenNotAssociatedWithBatch) || errors.Is(err, service.ErrPenNotEmpty) { + controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), action, err.Error(), batchID) + return + } + c.logger.Errorf("%s: 业务逻辑失败: %v", action, err) + controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "记录病猪死亡事件失败", action, err.Error(), batchID) + return + } + + controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "记录成功", nil, action, "记录成功", batchID) +} + +// RecordSickPigCull godoc +// @Summary 记录病猪淘汰事件 +// @Description 记录猪批次中病猪淘汰的数量、治疗地点和发生时间 +// @Tags 猪批次管理 +// @Accept json +// @Produce json +// @Param id path int true "猪批次ID" +// @Param body body dto.RecordSickPigCullRequest true "记录病猪淘汰请求信息" +// @Success 200 {object} controller.Response "记录成功" +// @Router /api/v1/pig-batches/{id}/record-sick-pig-cull [post] +func (c *PigBatchController) RecordSickPigCull(ctx *gin.Context) { + const action = "记录病猪淘汰事件" + batchID, err := strconv.ParseUint(ctx.Param("id"), 10, 32) + if err != nil { + controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的猪批次ID格式", action, "ID格式错误", ctx.Param("id")) + return + } + + var req dto.RecordSickPigCullRequest + if err := ctx.ShouldBindJSON(&req); err != nil { + controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req) + return + } + + operatorID, err := controller.GetOperatorIDFromContext(ctx) + + err = c.service.RecordSickPigCull(operatorID, uint(batchID), req.PenID, req.Quantity, req.TreatmentLocation, req.HappenedAt, req.Remarks) + if err != nil { + if errors.Is(err, service.ErrPigBatchNotFound) || errors.Is(err, service.ErrPenNotFound) { + controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), action, err.Error(), batchID) + return + } else if errors.Is(err, service.ErrInvalidOperation) || errors.Is(err, service.ErrPigBatchNotActive) || errors.Is(err, service.ErrPenNotAssociatedWithBatch) || errors.Is(err, service.ErrPenNotEmpty) { + controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), action, err.Error(), batchID) + return + } + c.logger.Errorf("%s: 业务逻辑失败: %v", action, err) + controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "记录病猪淘汰事件失败", action, err.Error(), batchID) + return + } + + controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "记录成功", nil, action, "记录成功", batchID) +} + +// RecordDeath godoc +// @Summary 记录正常猪只死亡事件 +// @Description 记录猪批次中正常猪只死亡的数量和发生时间 +// @Tags 猪批次管理 +// @Accept json +// @Produce json +// @Param id path int true "猪批次ID" +// @Param body body dto.RecordDeathRequest true "记录正常猪只死亡请求信息" +// @Success 200 {object} controller.Response "记录成功" +// @Router /api/v1/pig-batches/{id}/record-death [post] +func (c *PigBatchController) RecordDeath(ctx *gin.Context) { + const action = "记录正常猪只死亡事件" + batchID, err := strconv.ParseUint(ctx.Param("id"), 10, 32) + if err != nil { + controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的猪批次ID格式", action, "ID格式错误", ctx.Param("id")) + return + } + + var req dto.RecordDeathRequest + if err := ctx.ShouldBindJSON(&req); err != nil { + controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req) + return + } + + operatorID, err := controller.GetOperatorIDFromContext(ctx) + + err = c.service.RecordDeath(operatorID, uint(batchID), req.PenID, req.Quantity, req.HappenedAt, req.Remarks) + if err != nil { + if errors.Is(err, service.ErrPigBatchNotFound) || errors.Is(err, service.ErrPenNotFound) { + controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), action, err.Error(), batchID) + return + } else if errors.Is(err, service.ErrInvalidOperation) || errors.Is(err, service.ErrPigBatchNotActive) || errors.Is(err, service.ErrPenNotAssociatedWithBatch) || errors.Is(err, service.ErrPenNotEmpty) { + controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), action, err.Error(), batchID) + return + } + c.logger.Errorf("%s: 业务逻辑失败: %v", action, err) + controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "记录正常猪只死亡事件失败", action, err.Error(), batchID) + return + } + + controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "记录成功", nil, action, "记录成功", batchID) +} + +// RecordCull godoc +// @Summary 记录正常猪只淘汰事件 +// @Description 记录猪批次中正常猪只淘汰的数量和发生时间 +// @Tags 猪批次管理 +// @Accept json +// @Produce json +// @Param id path int true "猪批次ID" +// @Param body body dto.RecordCullRequest true "记录正常猪只淘汰请求信息" +// @Success 200 {object} controller.Response "记录成功" +// @Router /api/v1/pig-batches/{id}/record-cull [post] +func (c *PigBatchController) RecordCull(ctx *gin.Context) { + const action = "记录正常猪只淘汰事件" + batchID, err := strconv.ParseUint(ctx.Param("id"), 10, 32) + if err != nil { + controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的猪批次ID格式", action, "ID格式错误", ctx.Param("id")) + return + } + + var req dto.RecordCullRequest + if err := ctx.ShouldBindJSON(&req); err != nil { + controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req) + return + } + + operatorID, err := controller.GetOperatorIDFromContext(ctx) + + err = c.service.RecordCull(operatorID, uint(batchID), req.PenID, req.Quantity, req.HappenedAt, req.Remarks) + if err != nil { + if errors.Is(err, service.ErrPigBatchNotFound) || errors.Is(err, service.ErrPenNotFound) { + controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), action, err.Error(), batchID) + return + } else if errors.Is(err, service.ErrInvalidOperation) || errors.Is(err, service.ErrPigBatchNotActive) || errors.Is(err, service.ErrPenNotAssociatedWithBatch) || errors.Is(err, service.ErrPenNotEmpty) { + controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), action, err.Error(), batchID) + return + } + c.logger.Errorf("%s: 业务逻辑失败: %v", action, err) + controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "记录正常猪只淘汰事件失败", action, err.Error(), batchID) + return + } + + controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "记录成功", nil, action, "记录成功", batchID) +} diff --git a/internal/app/controller/management/pig_batch_trade_controller.go b/internal/app/controller/management/pig_batch_trade_controller.go new file mode 100644 index 0000000..821203c --- /dev/null +++ b/internal/app/controller/management/pig_batch_trade_controller.go @@ -0,0 +1,97 @@ +package management + +import ( + "errors" + "strconv" + + "git.huangwc.com/pig/pig-farm-controller/internal/app/controller" + "git.huangwc.com/pig/pig-farm-controller/internal/app/dto" + "git.huangwc.com/pig/pig-farm-controller/internal/app/service" + "github.com/gin-gonic/gin" +) + +// SellPigs godoc +// @Summary 处理卖猪的业务逻辑 +// @Description 记录猪批次中的猪只出售事件 +// @Tags 猪批次管理 +// @Accept json +// @Produce json +// @Param id path int true "猪批次ID" +// @Param body body dto.SellPigsRequest true "卖猪请求信息" +// @Success 200 {object} controller.Response "卖猪成功" +// @Router /api/v1/pig-batches/{id}/sell-pigs [post] +func (c *PigBatchController) SellPigs(ctx *gin.Context) { + const action = "卖猪" + batchID, err := strconv.ParseUint(ctx.Param("id"), 10, 32) + if err != nil { + controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的猪批次ID格式", action, "ID格式错误", ctx.Param("id")) + return + } + + var req dto.SellPigsRequest + if err := ctx.ShouldBindJSON(&req); err != nil { + controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req) + return + } + + operatorID, err := controller.GetOperatorIDFromContext(ctx) + + err = c.service.SellPigs(uint(batchID), req.PenID, req.Quantity, req.UnitPrice, req.TotalPrice, req.TraderName, req.TradeDate, req.Remarks, operatorID) + if err != nil { + if errors.Is(err, service.ErrPigBatchNotFound) || errors.Is(err, service.ErrPenNotFound) { + controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), action, err.Error(), batchID) + return + } else if errors.Is(err, service.ErrInvalidOperation) || errors.Is(err, service.ErrPigBatchNotActive) || errors.Is(err, service.ErrPenNotAssociatedWithBatch) || errors.Is(err, service.ErrPenNotEmpty) { + controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), action, err.Error(), batchID) + return + } + c.logger.Errorf("%s: 业务逻辑失败: %v", action, err) + controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "卖猪失败", action, err.Error(), batchID) + return + } + + controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "卖猪成功", nil, action, "卖猪成功", batchID) +} + +// BuyPigs godoc +// @Summary 处理买猪的业务逻辑 +// @Description 记录猪批次中的猪只购买事件 +// @Tags 猪批次管理 +// @Accept json +// @Produce json +// @Param id path int true "猪批次ID" +// @Param body body dto.BuyPigsRequest true "买猪请求信息" +// @Success 200 {object} controller.Response "买猪成功" +// @Router /api/v1/pig-batches/{id}/buy-pigs [post] +func (c *PigBatchController) BuyPigs(ctx *gin.Context) { + const action = "买猪" + batchID, err := strconv.ParseUint(ctx.Param("id"), 10, 32) + if err != nil { + controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的猪批次ID格式", action, "ID格式错误", ctx.Param("id")) + return + } + + var req dto.BuyPigsRequest + if err := ctx.ShouldBindJSON(&req); err != nil { + controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req) + return + } + + operatorID, err := controller.GetOperatorIDFromContext(ctx) + + err = c.service.BuyPigs(uint(batchID), req.PenID, req.Quantity, req.UnitPrice, req.TotalPrice, req.TraderName, req.TradeDate, req.Remarks, operatorID) + if err != nil { + if errors.Is(err, service.ErrPigBatchNotFound) || errors.Is(err, service.ErrPenNotFound) { + controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), action, err.Error(), batchID) + return + } else if errors.Is(err, service.ErrInvalidOperation) || errors.Is(err, service.ErrPigBatchNotActive) || errors.Is(err, service.ErrPenNotAssociatedWithBatch) { + controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), action, err.Error(), batchID) + return + } + c.logger.Errorf("%s: 业务逻辑失败: %v", action, err) + controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "买猪失败", action, err.Error(), batchID) + return + } + + controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "买猪成功", nil, action, "买猪成功", batchID) +} diff --git a/internal/app/controller/management/pig_batch_transfer_controller.go b/internal/app/controller/management/pig_batch_transfer_controller.go new file mode 100644 index 0000000..637367b --- /dev/null +++ b/internal/app/controller/management/pig_batch_transfer_controller.go @@ -0,0 +1,97 @@ +package management + +import ( + "errors" + "strconv" + + "git.huangwc.com/pig/pig-farm-controller/internal/app/controller" + "git.huangwc.com/pig/pig-farm-controller/internal/app/dto" + "git.huangwc.com/pig/pig-farm-controller/internal/app/service" + "github.com/gin-gonic/gin" +) + +// TransferPigsAcrossBatches godoc +// @Summary 跨猪群调栏 +// @Description 将指定数量的猪只从一个猪群的猪栏调动到另一个猪群的猪栏 +// @Tags 猪批次管理 +// @Accept json +// @Produce json +// @Param sourceBatchID path int true "源猪批次ID" +// @Param body body dto.TransferPigsAcrossBatchesRequest true "跨群调栏请求信息" +// @Success 200 {object} controller.Response "调栏成功" +// @Router /api/v1/pig-batches/{sourceBatchID}/transfer-across-batches [post] +func (c *PigBatchController) TransferPigsAcrossBatches(ctx *gin.Context) { + const action = "跨猪群调栏" + sourceBatchID, err := strconv.ParseUint(ctx.Param("sourceBatchID"), 10, 32) + if err != nil { + controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的源猪批次ID格式", action, "ID格式错误", ctx.Param("sourceBatchID")) + return + } + + var req dto.TransferPigsAcrossBatchesRequest + if err := ctx.ShouldBindJSON(&req); err != nil { + controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req) + return + } + + operatorID, err := controller.GetOperatorIDFromContext(ctx) + + err = c.service.TransferPigsAcrossBatches(uint(sourceBatchID), req.DestBatchID, req.FromPenID, req.ToPenID, req.Quantity, operatorID, req.Remarks) + if err != nil { + if errors.Is(err, service.ErrPigBatchNotFound) || errors.Is(err, service.ErrPenNotFound) { + controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), action, err.Error(), sourceBatchID) + return + } else if errors.Is(err, service.ErrInvalidOperation) || errors.Is(err, service.ErrPigBatchNotActive) || errors.Is(err, service.ErrPenNotAssociatedWithBatch) { + controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), action, err.Error(), sourceBatchID) + return + } + c.logger.Errorf("%s: 业务逻辑失败: %v", action, err) + controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "跨猪群调栏失败", action, err.Error(), sourceBatchID) + return + } + + controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "调栏成功", nil, action, "调栏成功", sourceBatchID) +} + +// TransferPigsWithinBatch godoc +// @Summary 群内调栏 +// @Description 将指定数量的猪只在同一个猪群的不同猪栏间调动 +// @Tags 猪批次管理 +// @Accept json +// @Produce json +// @Param id path int true "猪批次ID" +// @Param body body dto.TransferPigsWithinBatchRequest true "群内调栏请求信息" +// @Success 200 {object} controller.Response "调栏成功" +// @Router /api/v1/pig-batches/{id}/transfer-within-batch [post] +func (c *PigBatchController) TransferPigsWithinBatch(ctx *gin.Context) { + const action = "群内调栏" + batchID, err := strconv.ParseUint(ctx.Param("id"), 10, 32) + if err != nil { + controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的猪批次ID格式", action, "ID格式错误", ctx.Param("id")) + return + } + + var req dto.TransferPigsWithinBatchRequest + if err := ctx.ShouldBindJSON(&req); err != nil { + controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req) + return + } + + operatorID, err := controller.GetOperatorIDFromContext(ctx) + + err = c.service.TransferPigsWithinBatch(uint(batchID), req.FromPenID, req.ToPenID, req.Quantity, operatorID, req.Remarks) + if err != nil { + if errors.Is(err, service.ErrPigBatchNotFound) || errors.Is(err, service.ErrPenNotFound) { + controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), action, err.Error(), batchID) + return + } else if errors.Is(err, service.ErrInvalidOperation) || errors.Is(err, service.ErrPigBatchNotActive) || errors.Is(err, service.ErrPenNotAssociatedWithBatch) { + controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), action, err.Error(), batchID) + return + } + c.logger.Errorf("%s: 业务逻辑失败: %v", action, err) + controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "群内调栏失败", action, err.Error(), batchID) + return + } + + controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "调栏成功", nil, action, "调栏成功", batchID) +} diff --git a/internal/app/dto/pig_batch_dto.go b/internal/app/dto/pig_batch_dto.go index 47b539e..8485d87 100644 --- a/internal/app/dto/pig_batch_dto.go +++ b/internal/app/dto/pig_batch_dto.go @@ -67,3 +67,94 @@ type MovePigsIntoPenRequest struct { Quantity int `json:"quantity" binding:"required,min=1"` // 移入猪只数量 Remarks string `json:"remarks"` // 备注 } + +// SellPigsRequest 用于处理卖猪的请求体 +type SellPigsRequest struct { + PenID uint `json:"penID" binding:"required"` // 猪栏ID + Quantity int `json:"quantity" binding:"required,min=1"` // 卖出猪只数量 + UnitPrice float64 `json:"unitPrice" binding:"required,min=0"` // 单价 + TotalPrice float64 `json:"totalPrice" binding:"required,min=0"` // 总价 + TraderName string `json:"traderName" binding:"required"` // 交易方名称 + TradeDate time.Time `json:"tradeDate" binding:"required"` // 交易日期 + Remarks string `json:"remarks"` // 备注 +} + +// BuyPigsRequest 用于处理买猪的请求体 +type BuyPigsRequest struct { + PenID uint `json:"penID" binding:"required"` // 猪栏ID + Quantity int `json:"quantity" binding:"required,min=1"` // 买入猪只数量 + UnitPrice float64 `json:"unitPrice" binding:"required,min=0"` // 单价 + TotalPrice float64 `json:"totalPrice" binding:"required,min=0"` // 总价 + TraderName string `json:"traderName" binding:"required"` // 交易方名称 + TradeDate time.Time `json:"tradeDate" binding:"required"` // 交易日期 + Remarks string `json:"remarks"` // 备注 +} + +// TransferPigsAcrossBatchesRequest 用于跨猪群调栏的请求体 +type TransferPigsAcrossBatchesRequest struct { + DestBatchID uint `json:"destBatchID" binding:"required"` // 目标猪批次ID + FromPenID uint `json:"fromPenID" binding:"required"` // 源猪栏ID + ToPenID uint `json:"toPenID" binding:"required"` // 目标猪栏ID + Quantity uint `json:"quantity" binding:"required,min=1"` // 调栏猪只数量 + Remarks string `json:"remarks"` // 备注 +} + +// TransferPigsWithinBatchRequest 用于群内调栏的请求体 +type TransferPigsWithinBatchRequest struct { + FromPenID uint `json:"fromPenID" binding:"required"` // 源猪栏ID + ToPenID uint `json:"toPenID" binding:"required"` // 目标猪栏ID + Quantity uint `json:"quantity" binding:"required,min=1"` // 调栏猪只数量 + Remarks string `json:"remarks"` // 备注 +} + +// RecordSickPigsRequest 用于记录新增病猪事件的请求体 +type RecordSickPigsRequest struct { + PenID uint `json:"penID" binding:"required"` // 猪栏ID + Quantity int `json:"quantity" binding:"required,min=1"` // 病猪数量 + TreatmentLocation models.PigBatchSickPigTreatmentLocation `json:"treatmentLocation" binding:"required"` // 治疗地点 + HappenedAt time.Time `json:"happenedAt" binding:"required"` // 发生时间 + Remarks string `json:"remarks"` // 备注 +} + +// RecordSickPigRecoveryRequest 用于记录病猪康复事件的请求体 +type RecordSickPigRecoveryRequest struct { + PenID uint `json:"penID" binding:"required"` // 猪栏ID + Quantity int `json:"quantity" binding:"required,min=1"` // 康复猪数量 + TreatmentLocation models.PigBatchSickPigTreatmentLocation `json:"treatmentLocation" binding:"required"` // 治疗地点 + HappenedAt time.Time `json:"happenedAt" binding:"required"` // 发生时间 + Remarks string `json:"remarks"` // 备注 +} + +// RecordSickPigDeathRequest 用于记录病猪死亡事件的请求体 +type RecordSickPigDeathRequest struct { + PenID uint `json:"penID" binding:"required"` // 猪栏ID + Quantity int `json:"quantity" binding:"required,min=1"` // 死亡猪数量 + TreatmentLocation models.PigBatchSickPigTreatmentLocation `json:"treatmentLocation" binding:"required"` // 治疗地点 + HappenedAt time.Time `json:"happenedAt" binding:"required"` // 发生时间 + Remarks string `json:"remarks"` // 备注 +} + +// RecordSickPigCullRequest 用于记录病猪淘汰事件的请求体 +type RecordSickPigCullRequest struct { + PenID uint `json:"penID" binding:"required"` // 猪栏ID + Quantity int `json:"quantity" binding:"required,min=1"` // 淘汰猪数量 + TreatmentLocation models.PigBatchSickPigTreatmentLocation `json:"treatmentLocation" binding:"required"` // 治疗地点 + HappenedAt time.Time `json:"happenedAt" binding:"required"` // 发生时间 + Remarks string `json:"remarks"` // 备注 +} + +// RecordDeathRequest 用于记录正常猪只死亡事件的请求体 +type RecordDeathRequest struct { + PenID uint `json:"penID" binding:"required"` // 猪栏ID + Quantity int `json:"quantity" binding:"required,min=1"` // 死亡猪数量 + HappenedAt time.Time `json:"happenedAt" binding:"required"` // 发生时间 + Remarks string `json:"remarks"` // 备注 +} + +// RecordCullRequest 用于记录正常猪只淘汰事件的请求体 +type RecordCullRequest struct { + PenID uint `json:"penID" binding:"required"` // 猪栏ID + Quantity int `json:"quantity" binding:"required,min=1"` // 淘汰猪数量 + HappenedAt time.Time `json:"happenedAt" binding:"required"` // 发生时间 + Remarks string `json:"remarks"` // 备注 +} diff --git a/internal/app/service/pig_batch_service.go b/internal/app/service/pig_batch_service.go index 32111d4..4f362c5 100644 --- a/internal/app/service/pig_batch_service.go +++ b/internal/app/service/pig_batch_service.go @@ -1,6 +1,8 @@ package service import ( + "time" + "git.huangwc.com/pig/pig-farm-controller/internal/app/dto" domain_pig "git.huangwc.com/pig/pig-farm-controller/internal/domain/pig" "git.huangwc.com/pig/pig-farm-controller/internal/infra/logs" @@ -14,10 +16,30 @@ type PigBatchService interface { UpdatePigBatch(id uint, dto *dto.PigBatchUpdateDTO) (*dto.PigBatchResponseDTO, error) DeletePigBatch(id uint) error ListPigBatches(isActive *bool) ([]*dto.PigBatchResponseDTO, error) + + // Pig Pen Management AssignEmptyPensToBatch(batchID uint, penIDs []uint, operatorID uint) error ReclassifyPenToNewBatch(fromBatchID uint, toBatchID uint, penID uint, operatorID uint, remarks string) error RemoveEmptyPenFromBatch(batchID uint, penID uint) error MovePigsIntoPen(batchID uint, toPenID uint, quantity int, operatorID uint, remarks string) error + + // Trade Sub-service + SellPigs(batchID uint, penID uint, quantity int, unitPrice float64, tatalPrice float64, traderName string, tradeDate time.Time, remarks string, operatorID uint) error + BuyPigs(batchID uint, penID uint, quantity int, unitPrice float64, tatalPrice float64, traderName string, tradeDate time.Time, remarks string, operatorID uint) error + + // Transfer Sub-service + TransferPigsAcrossBatches(sourceBatchID uint, destBatchID uint, fromPenID uint, toPenID uint, quantity uint, operatorID uint, remarks string) error + TransferPigsWithinBatch(batchID uint, fromPenID uint, toPenID uint, quantity uint, operatorID uint, remarks string) error + + // Sick Pig Management + RecordSickPigs(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error + RecordSickPigRecovery(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error + RecordSickPigDeath(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error + RecordSickPigCull(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error + + // Normal Pig Management + RecordDeath(operatorID uint, batchID uint, penID uint, quantity int, happenedAt time.Time, remarks string) error + RecordCull(operatorID uint, batchID uint, penID uint, quantity int, happenedAt time.Time, remarks string) error } // pigBatchService 的实现现在依赖于领域服务接口。 @@ -191,3 +213,103 @@ func (s *pigBatchService) MovePigsIntoPen(batchID uint, toPenID uint, quantity i } return nil } + +// SellPigs 委托给领域服务 +func (s *pigBatchService) SellPigs(batchID uint, penID uint, quantity int, unitPrice float64, tatalPrice float64, traderName string, tradeDate time.Time, remarks string, operatorID uint) error { + err := s.domainService.SellPigs(batchID, penID, quantity, unitPrice, tatalPrice, traderName, tradeDate, remarks, operatorID) + if err != nil { + s.logger.Errorf("应用层: 卖猪失败, 批次ID: %d, 错误: %v", batchID, err) + return MapDomainError(err) + } + return nil +} + +// BuyPigs 委托给领域服务 +func (s *pigBatchService) BuyPigs(batchID uint, penID uint, quantity int, unitPrice float64, tatalPrice float64, traderName string, tradeDate time.Time, remarks string, operatorID uint) error { + err := s.domainService.BuyPigs(batchID, penID, quantity, unitPrice, tatalPrice, traderName, tradeDate, remarks, operatorID) + if err != nil { + s.logger.Errorf("应用层: 买猪失败, 批次ID: %d, 错误: %v", batchID, err) + return MapDomainError(err) + } + return nil +} + +// TransferPigsAcrossBatches 委托给领域服务 +func (s *pigBatchService) TransferPigsAcrossBatches(sourceBatchID uint, destBatchID uint, fromPenID uint, toPenID uint, quantity uint, operatorID uint, remarks string) error { + err := s.domainService.TransferPigsAcrossBatches(sourceBatchID, destBatchID, fromPenID, toPenID, quantity, operatorID, remarks) + if err != nil { + s.logger.Errorf("应用层: 跨群调栏失败, 源批次ID: %d, 错误: %v", sourceBatchID, err) + return MapDomainError(err) + } + return nil +} + +// TransferPigsWithinBatch 委托给领域服务 +func (s *pigBatchService) TransferPigsWithinBatch(batchID uint, fromPenID uint, toPenID uint, quantity uint, operatorID uint, remarks string) error { + err := s.domainService.TransferPigsWithinBatch(batchID, fromPenID, toPenID, quantity, operatorID, remarks) + if err != nil { + s.logger.Errorf("应用层: 群内调栏失败, 批次ID: %d, 错误: %v", batchID, err) + return MapDomainError(err) + } + return nil +} + +// RecordSickPigs 委托给领域服务 +func (s *pigBatchService) RecordSickPigs(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error { + err := s.domainService.RecordSickPigs(operatorID, batchID, penID, quantity, treatmentLocation, happenedAt, remarks) + if err != nil { + s.logger.Errorf("应用层: 记录病猪事件失败, 批次ID: %d, 错误: %v", batchID, err) + return MapDomainError(err) + } + return nil +} + +// RecordSickPigRecovery 委托给领域服务 +func (s *pigBatchService) RecordSickPigRecovery(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error { + err := s.domainService.RecordSickPigRecovery(operatorID, batchID, penID, quantity, treatmentLocation, happenedAt, remarks) + if err != nil { + s.logger.Errorf("应用层: 记录病猪康复事件失败, 批次ID: %d, 错误: %v", batchID, err) + return MapDomainError(err) + } + return nil +} + +// RecordSickPigDeath 委托给领域服务 +func (s *pigBatchService) RecordSickPigDeath(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error { + err := s.domainService.RecordSickPigDeath(operatorID, batchID, penID, quantity, treatmentLocation, happenedAt, remarks) + if err != nil { + s.logger.Errorf("应用层: 记录病猪死亡事件失败, 批次ID: %d, 错误: %v", batchID, err) + return MapDomainError(err) + } + return nil +} + +// RecordSickPigCull 委托给领域服务 +func (s *pigBatchService) RecordSickPigCull(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error { + err := s.domainService.RecordSickPigCull(operatorID, batchID, penID, quantity, treatmentLocation, happenedAt, remarks) + if err != nil { + s.logger.Errorf("应用层: 记录病猪淘汰事件失败, 批次ID: %d, 错误: %v", batchID, err) + return MapDomainError(err) + } + return nil +} + +// RecordDeath 委托给领域服务 +func (s *pigBatchService) RecordDeath(operatorID uint, batchID uint, penID uint, quantity int, happenedAt time.Time, remarks string) error { + err := s.domainService.RecordDeath(operatorID, batchID, penID, quantity, happenedAt, remarks) + if err != nil { + s.logger.Errorf("应用层: 记录正常猪只死亡事件失败, 批次ID: %d, 错误: %v", batchID, err) + return MapDomainError(err) + } + return nil +} + +// RecordCull 委托给领域服务 +func (s *pigBatchService) RecordCull(operatorID uint, batchID uint, penID uint, quantity int, happenedAt time.Time, remarks string) error { + err := s.domainService.RecordCull(operatorID, batchID, penID, quantity, happenedAt, remarks) + if err != nil { + s.logger.Errorf("应用层: 记录正常猪只淘汰事件失败, 批次ID: %d, 错误: %v", batchID, err) + return MapDomainError(err) + } + return nil +}