301 lines
8.3 KiB
Go
301 lines
8.3 KiB
Go
package handler
|
|
|
|
import (
|
|
"net/http"
|
|
"time"
|
|
|
|
"silk-server-go/internal/middleware"
|
|
"silk-server-go/internal/model"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// RegisterTrayBatchRoutes 注册蚕匾/批次/饲养记录路由
|
|
func RegisterTrayBatchRoutes(rg *gin.RouterGroup, db *gorm.DB) {
|
|
trayRead := middleware.RequirePermission(db, "tray:read")
|
|
trayWrite := middleware.RequirePermission(db, "tray:write")
|
|
batchRead := middleware.RequirePermission(db, "batch:read")
|
|
batchWrite := middleware.RequirePermission(db, "batch:write")
|
|
rearingRead := middleware.RequirePermission(db, "rearing:read")
|
|
rearingWrite := middleware.RequirePermission(db, "rearing:write")
|
|
|
|
rg.GET("/trays", trayRead, listTrays(db))
|
|
rg.POST("/trays", trayWrite, createTray(db))
|
|
rg.PATCH("/trays/:id", trayWrite, updateTray(db))
|
|
rg.DELETE("/trays/:id", trayWrite, deleteTray(db))
|
|
|
|
rg.GET("/batches", batchRead, listBatches(db))
|
|
rg.POST("/batches", batchWrite, createBatch(db))
|
|
rg.PATCH("/batches/:id", batchWrite, updateBatch(db))
|
|
rg.DELETE("/batches/:id", batchWrite, deleteBatch(db))
|
|
|
|
rg.GET("/rearing-records", rearingRead, listRearingRecords(db))
|
|
rg.POST("/rearing-records", rearingWrite, createRearingRecord(db))
|
|
rg.PATCH("/rearing-records/:id", rearingWrite, updateRearingRecord(db))
|
|
rg.DELETE("/rearing-records/:id", rearingWrite, deleteRearingRecord(db))
|
|
}
|
|
|
|
// ---------- 蚕匾 ----------
|
|
|
|
func listTrays(db *gorm.DB) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
q := applyRoomScope(db.Model(&model.Tray{}), c, "room_id")
|
|
if room := c.Query("roomId"); room != "" {
|
|
q = q.Where("room_id = ?", room)
|
|
}
|
|
if enabled := c.Query("enabled"); enabled != "" {
|
|
q = q.Where("enabled = ?", enabled == "true")
|
|
}
|
|
var list []model.Tray
|
|
q.Order("name ASC").Find(&list)
|
|
c.JSON(http.StatusOK, list)
|
|
}
|
|
}
|
|
|
|
func createTray(db *gorm.DB) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
var t model.Tray
|
|
if err := c.ShouldBindJSON(&t); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
t.ID = ""
|
|
if t.Name == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "蚕匾名称不能为空"})
|
|
return
|
|
}
|
|
if !isUUID(t.RoomID) {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "roomId 不是合法的 UUID"})
|
|
return
|
|
}
|
|
if !canAccessRoom(db, c, &t.RoomID) {
|
|
c.JSON(http.StatusForbidden, gin.H{"error": "无权在该蚕房下创建蚕匾"})
|
|
return
|
|
}
|
|
if err := db.Create(&t).Error; err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "创建失败"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusCreated, t)
|
|
}
|
|
}
|
|
|
|
func updateTray(db *gorm.DB) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
id := c.Param("id")
|
|
if !requireObjectAccess(c, db, "tray", id) {
|
|
return
|
|
}
|
|
var t model.Tray
|
|
if db.Where("id = ?", id).First(&t).Error != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "tray not found"})
|
|
return
|
|
}
|
|
updates, err := bindUpdates(c)
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
if roomID, ok := updates["room_id"].(string); ok && !canAccessRoom(db, c, &roomID) {
|
|
c.JSON(http.StatusForbidden, gin.H{"error": "无权迁移蚕匾到指定蚕房"})
|
|
return
|
|
}
|
|
if len(updates) > 0 {
|
|
db.Model(&model.Tray{}).Where("id = ?", id).Updates(updates)
|
|
}
|
|
db.Where("id = ?", id).First(&t)
|
|
c.JSON(http.StatusOK, t)
|
|
}
|
|
}
|
|
|
|
func deleteTray(db *gorm.DB) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
id := c.Param("id")
|
|
if !requireObjectAccess(c, db, "tray", id) {
|
|
return
|
|
}
|
|
var t model.Tray
|
|
if db.Where("id = ?", id).First(&t).Error != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "tray not found"})
|
|
return
|
|
}
|
|
db.Where("id = ?", id).Delete(&model.Tray{})
|
|
c.JSON(http.StatusOK, gin.H{"id": id})
|
|
}
|
|
}
|
|
|
|
// ---------- 批次 ----------
|
|
|
|
func listBatches(db *gorm.DB) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
q := applyRoomScope(db.Model(&model.Batch{}), c, "room_id")
|
|
if room := c.Query("roomId"); room != "" {
|
|
q = q.Where("room_id = ?", room)
|
|
}
|
|
if status := c.Query("status"); status != "" {
|
|
q = q.Where("status = ?", status)
|
|
}
|
|
var list []model.Batch
|
|
q.Order("created_at DESC").Find(&list)
|
|
c.JSON(http.StatusOK, list)
|
|
}
|
|
}
|
|
|
|
func createBatch(db *gorm.DB) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
var b model.Batch
|
|
if err := c.ShouldBindJSON(&b); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
b.ID = ""
|
|
if b.Name == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "批次名称不能为空"})
|
|
return
|
|
}
|
|
if !isUUID(b.RoomID) {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "roomId 不是合法的 UUID"})
|
|
return
|
|
}
|
|
if !canAccessRoom(db, c, &b.RoomID) {
|
|
c.JSON(http.StatusForbidden, gin.H{"error": "无权在该蚕房下创建批次"})
|
|
return
|
|
}
|
|
if b.Status == "" {
|
|
b.Status = "rearing"
|
|
}
|
|
if err := db.Create(&b).Error; err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "创建失败"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusCreated, b)
|
|
}
|
|
}
|
|
|
|
func updateBatch(db *gorm.DB) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
id := c.Param("id")
|
|
if !requireObjectAccess(c, db, "batch", id) {
|
|
return
|
|
}
|
|
var b model.Batch
|
|
if db.Where("id = ?", id).First(&b).Error != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "batch not found"})
|
|
return
|
|
}
|
|
updates, err := bindUpdates(c)
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
if roomID, ok := updates["room_id"].(string); ok && !canAccessRoom(db, c, &roomID) {
|
|
c.JSON(http.StatusForbidden, gin.H{"error": "无权迁移批次到指定蚕房"})
|
|
return
|
|
}
|
|
if len(updates) > 0 {
|
|
db.Model(&model.Batch{}).Where("id = ?", id).Updates(updates)
|
|
}
|
|
db.Where("id = ?", id).First(&b)
|
|
c.JSON(http.StatusOK, b)
|
|
}
|
|
}
|
|
|
|
func deleteBatch(db *gorm.DB) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
id := c.Param("id")
|
|
if !requireObjectAccess(c, db, "batch", id) {
|
|
return
|
|
}
|
|
var b model.Batch
|
|
if db.Where("id = ?", id).First(&b).Error != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "batch not found"})
|
|
return
|
|
}
|
|
// 级联删除饲养记录
|
|
db.Where("batch_id = ?", id).Delete(&model.RearingRecord{})
|
|
db.Where("id = ?", id).Delete(&model.Batch{})
|
|
c.JSON(http.StatusOK, gin.H{"id": id})
|
|
}
|
|
}
|
|
|
|
// ---------- 饲养记录 ----------
|
|
|
|
func listRearingRecords(db *gorm.DB) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
q := applyRoomScope(db.Table("rearing_records").Joins("JOIN batches b ON b.id = rearing_records.batch_id"), c, "b.room_id")
|
|
if batch := c.Query("batchId"); batch != "" {
|
|
q = q.Where("batch_id = ?", batch)
|
|
}
|
|
var list []model.RearingRecord
|
|
q.Order("record_date DESC").Find(&list)
|
|
c.JSON(http.StatusOK, list)
|
|
}
|
|
}
|
|
|
|
func createRearingRecord(db *gorm.DB) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
var r model.RearingRecord
|
|
if err := c.ShouldBindJSON(&r); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
r.ID = ""
|
|
if !isUUID(r.BatchID) {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "batchId 不是合法的 UUID"})
|
|
return
|
|
}
|
|
if !requireObjectAccess(c, db, "batch", r.BatchID) {
|
|
return
|
|
}
|
|
if r.RecordDate.IsZero() {
|
|
r.RecordDate = time.Now()
|
|
}
|
|
if err := db.Create(&r).Error; err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "创建失败"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusCreated, r)
|
|
}
|
|
}
|
|
|
|
func updateRearingRecord(db *gorm.DB) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
id := c.Param("id")
|
|
if !requireObjectAccess(c, db, "rearing_record", id) {
|
|
return
|
|
}
|
|
var r model.RearingRecord
|
|
if db.Where("id = ?", id).First(&r).Error != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "rearing record not found"})
|
|
return
|
|
}
|
|
updates, err := bindUpdates(c)
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
if len(updates) > 0 {
|
|
db.Model(&model.RearingRecord{}).Where("id = ?", id).Updates(updates)
|
|
}
|
|
db.Where("id = ?", id).First(&r)
|
|
c.JSON(http.StatusOK, r)
|
|
}
|
|
}
|
|
|
|
func deleteRearingRecord(db *gorm.DB) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
id := c.Param("id")
|
|
if !requireObjectAccess(c, db, "rearing_record", id) {
|
|
return
|
|
}
|
|
var r model.RearingRecord
|
|
if db.Where("id = ?", id).First(&r).Error != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "rearing record not found"})
|
|
return
|
|
}
|
|
db.Where("id = ?", id).Delete(&model.RearingRecord{})
|
|
c.JSON(http.StatusOK, gin.H{"id": id})
|
|
}
|
|
}
|