diff --git a/backend/internal/handler/finance.go b/backend/internal/handler/finance.go index 1a0ea3f..107564a 100644 --- a/backend/internal/handler/finance.go +++ b/backend/internal/handler/finance.go @@ -173,7 +173,7 @@ func (h *FinanceHandler) Summary(c *gin.Context) { TotalAmount float64 `json:"total_amount"` } var rows []row - h.db.Raw(` + if err := h.db.Raw(` SELECT f.partner_id, COALESCE(p.name, '') AS partner_name, f.type, @@ -186,7 +186,10 @@ func (h *FinanceHandler) Summary(c *gin.Context) { AND f.status = 'open' GROUP BY f.partner_id, f.type ORDER BY total_amount DESC - `, shopID).Scan(&rows) + `, shopID).Scan(&rows).Error; err != nil { + util.RespondError(c, http.StatusInternalServerError, "QUERY_ERROR", "查询失败") + return + } util.RespondSuccess(c, rows) } diff --git a/backend/internal/handler/inventory.go b/backend/internal/handler/inventory.go index 0b117f1..95fba25 100644 --- a/backend/internal/handler/inventory.go +++ b/backend/internal/handler/inventory.go @@ -87,7 +87,10 @@ func (h *InventoryHandler) List(c *gin.Context) { WHERE ` + baseWhere var total int64 - h.db.Raw(countSQL, args...).Scan(&total) + if err := h.db.Raw(countSQL, args...).Scan(&total).Error; err != nil { + util.RespondError(c, http.StatusInternalServerError, "QUERY_ERROR", "查询失败") + return + } // Data query dataSQL := ` @@ -119,7 +122,10 @@ func (h *InventoryHandler) List(c *gin.Context) { dataArgs := append(args, pageSize, (page-1)*pageSize) var rows []inventoryRow - h.db.Raw(dataSQL, dataArgs...).Scan(&rows) + if err := h.db.Raw(dataSQL, dataArgs...).Scan(&rows).Error; err != nil { + util.RespondError(c, http.StatusInternalServerError, "QUERY_ERROR", "查询失败") + return + } c.JSON(http.StatusOK, gin.H{"data": rows, "total": total, "page": page, "page_size": pageSize}) } diff --git a/backend/internal/service/license.go b/backend/internal/service/license.go index c479d70..89d836e 100644 --- a/backend/internal/service/license.go +++ b/backend/internal/service/license.go @@ -74,7 +74,9 @@ func (s *LicenseService) Activate(shopID uint64, licenseKey, deviceID, deviceNam // New device — enforce max_devices var count int64 - s.db.Model(&model.LicenseDevice{}).Where("license_id = ?", lic.ID).Count(&count) + if err := s.db.Model(&model.LicenseDevice{}).Where("license_id = ?", lic.ID).Count(&count).Error; err != nil { + return nil, err + } if int(count) >= lic.MaxDevices { return nil, ErrDeviceLimitExceed } @@ -142,12 +144,11 @@ func (s *LicenseService) Deactivate(shopID uint64, deviceID string) error { } // createTrialLicense 在注册事务中为新门店签发 30 天 trial license。 -// 若私钥未配置则静默跳过(开发/测试环境可不配置私钥)。 +// 私钥未配置时 Fatal,防止生产环境静默跳过导致新注册门店无 license。 func createTrialLicense(tx *gorm.DB, shopID uint64) { privKey := config.C.License.Ed25519PrivateKey if privKey == "" { - log.Printf("[license] Ed25519 private key not configured, skipping trial for shop %d", shopID) - return + log.Fatalf("[license] Ed25519 private key not configured — cannot issue trial for shop %d; set License.Ed25519PrivateKey in config", shopID) } expiresAt := time.Now().Add(30 * 24 * time.Hour) diff --git a/backend/internal/service/stock.go b/backend/internal/service/stock.go index eeca154..aff0d70 100644 --- a/backend/internal/service/stock.go +++ b/backend/internal/service/stock.go @@ -52,10 +52,12 @@ func (s *StockService) ApproveStockIn(shopID, orderID, reviewerID uint64) error // 计算入库前库存总量(用于流水记录) var qtyBefore float64 - tx.Model(&model.Inventory{}). + if err := tx.Model(&model.Inventory{}). Where("shop_id = ? AND warehouse_id = ? AND product_id = ? AND deleted_at IS NULL", shopID, warehouseID, productID). - Select("COALESCE(SUM(quantity), 0)").Scan(&qtyBefore) + Select("COALESCE(SUM(quantity), 0)").Scan(&qtyBefore).Error; err != nil { + return err + } var unitPricePtr *float64 if itemCopy.UnitPrice != 0 { @@ -322,7 +324,7 @@ func (s *StockService) CheckInventoryAvailability(shopID, warehouseID uint64, it have := sumMap[item.ProductID] if have < item.Quantity { var p model.Product - s.db.Where("id = ?", item.ProductID).First(&p) + s.db.Where("id = ?", item.ProductID).First(&p) //nolint:errcheck — best-effort name lookup for error message name := p.Name if name == "" { name = fmt.Sprintf("商品ID %d", item.ProductID)