08f9e20010
Deploy Server / release-deploy-server (push) Successful in 1m30s
修复编辑入库单草稿后合计金额被清零(Update 漏累加 total) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YZ4DskSRKsSiheQonFtQvx
147 lines
4.2 KiB
Go
147 lines
4.2 KiB
Go
package handler
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"gorm.io/gorm"
|
|
|
|
"github.com/wangjia/jiu/backend/internal/middleware"
|
|
"github.com/wangjia/jiu/backend/internal/service"
|
|
"github.com/wangjia/jiu/backend/testutil"
|
|
)
|
|
|
|
// setupProtectedRouter 创建带 JWT 中间件的测试路由
|
|
func setupProtectedRouter(db *gorm.DB) *gin.Engine {
|
|
stockSvc := service.NewStockService(db)
|
|
licenseSvc := service.NewLicenseService(db)
|
|
|
|
productH := NewProductHandler(db)
|
|
stockInH := NewStockInHandler(db, stockSvc)
|
|
stockOutH := NewStockOutHandler(db, stockSvc)
|
|
inventoryH := NewInventoryHandler(db)
|
|
warehouseH := NewWarehouseHandler(db)
|
|
partnerH := NewPartnerHandler(db)
|
|
licenseH := NewLicenseHandler(licenseSvc)
|
|
|
|
r := gin.New()
|
|
r.Use(gin.Recovery())
|
|
|
|
api := r.Group("/api/v1")
|
|
api.Use(middleware.JWT(db))
|
|
|
|
// 商品路由
|
|
products := api.Group("/products")
|
|
products.GET("", productH.List)
|
|
products.POST("", productH.Create)
|
|
products.PUT("/:id", productH.Update)
|
|
products.DELETE("/:id", productH.Delete)
|
|
|
|
// 仓库路由
|
|
warehouses := api.Group("/warehouses")
|
|
warehouses.GET("", warehouseH.List)
|
|
warehouses.POST("", warehouseH.Create)
|
|
warehouses.PUT("/:id", warehouseH.Update)
|
|
warehouses.DELETE("/:id", warehouseH.Delete)
|
|
|
|
// 往来单位路由
|
|
partners := api.Group("/partners")
|
|
partners.GET("", partnerH.List)
|
|
partners.POST("", partnerH.Create)
|
|
partners.PUT("/:id", partnerH.Update)
|
|
partners.DELETE("/:id", partnerH.Delete)
|
|
|
|
// 入库路由
|
|
stockIn := api.Group("/stock-in")
|
|
stockIn.GET("/orders", stockInH.List)
|
|
stockIn.GET("/orders/:id", stockInH.Get)
|
|
stockIn.POST("/orders", stockInH.Create)
|
|
stockIn.PUT("/orders/:id", stockInH.Update)
|
|
stockIn.PUT("/orders/:id/submit", stockInH.Submit)
|
|
stockIn.PUT("/orders/:id/approve", stockInH.Approve)
|
|
stockIn.PUT("/orders/:id/reject", stockInH.Reject)
|
|
stockIn.PUT("/orders/:id/withdraw", stockInH.Withdraw)
|
|
stockIn.POST("/orders/:id/return", stockInH.Return)
|
|
|
|
// 出库路由
|
|
stockOut := api.Group("/stock-out")
|
|
stockOut.GET("/orders", stockOutH.List)
|
|
stockOut.GET("/orders/:id", stockOutH.Get)
|
|
stockOut.POST("/orders", stockOutH.Create)
|
|
stockOut.PUT("/orders/:id", stockOutH.Update)
|
|
stockOut.PUT("/orders/:id/submit", stockOutH.Submit)
|
|
stockOut.PUT("/orders/:id/approve", stockOutH.Approve)
|
|
stockOut.PUT("/orders/:id/reject", stockOutH.Reject)
|
|
stockOut.PUT("/orders/:id/withdraw", stockOutH.Withdraw)
|
|
stockOut.POST("/orders/:id/return", stockOutH.Return)
|
|
|
|
// 库存路由
|
|
inv := api.Group("/inventory")
|
|
inv.GET("", inventoryH.List)
|
|
inv.GET("/logs", inventoryH.Logs)
|
|
inv.POST("/checks", inventoryH.CreateCheck)
|
|
inv.GET("/checks/:id", inventoryH.GetCheck)
|
|
|
|
// 许可证路由
|
|
license := api.Group("/license")
|
|
license.POST("/activate", licenseH.Activate)
|
|
license.GET("/verify", licenseH.Verify)
|
|
license.POST("/deactivate", licenseH.Deactivate)
|
|
|
|
return r
|
|
}
|
|
|
|
// makeRequest 发起带认证的请求
|
|
func makeRequest(r *gin.Engine, method, path, token string, body interface{}) *httptest.ResponseRecorder {
|
|
var bodyBytes []byte
|
|
if body != nil {
|
|
bodyBytes, _ = json.Marshal(body)
|
|
}
|
|
|
|
w := httptest.NewRecorder()
|
|
req, _ := http.NewRequest(method, path, bytes.NewBuffer(bodyBytes))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
if token != "" {
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
}
|
|
r.ServeHTTP(w, req)
|
|
return w
|
|
}
|
|
|
|
// parseResponse 解析 JSON 响应
|
|
func parseResponse(w *httptest.ResponseRecorder) map[string]interface{} {
|
|
var resp map[string]interface{}
|
|
json.Unmarshal(w.Body.Bytes(), &resp)
|
|
return resp
|
|
}
|
|
|
|
// getAuthToken 为测试用户获取 token
|
|
func getAuthToken(userID, shopID uint64, role string) string {
|
|
return testutil.GetAuthToken(userID, shopID, role)
|
|
}
|
|
|
|
// extractID 从响应 data 中提取 id
|
|
func extractID(w *httptest.ResponseRecorder) uint64 {
|
|
resp := parseResponse(w)
|
|
if data, ok := resp["data"].(map[string]interface{}); ok {
|
|
if id, ok := data["id"].(float64); ok {
|
|
return uint64(id)
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// jsonBody 快速构建 JSON body
|
|
func jsonBody(kv ...interface{}) map[string]interface{} {
|
|
m := map[string]interface{}{}
|
|
for i := 0; i+1 < len(kv); i += 2 {
|
|
key := fmt.Sprintf("%v", kv[i])
|
|
m[key] = kv[i+1]
|
|
}
|
|
return m
|
|
}
|