feat: product proto type.

This commit is contained in:
2026-05-01 09:26:41 +08:00
parent 7b43ccf42f
commit f30cc1ea46
8 changed files with 663 additions and 2 deletions
+7
View File
@@ -20,6 +20,7 @@ type ProductInventory struct {
ID uint `gorm:"primaryKey" json:"id"`
ProductCode string `gorm:"size:64;not null;index" json:"productCode"`
ProjectTypeCode string `gorm:"size:64;index" json:"projectTypeCode"`
SuiteID *uint `gorm:"index" json:"suiteId"`
SuiteCode string `gorm:"size:128;index" json:"suiteCode"`
SerialNumber *string `gorm:"size:128;uniqueIndex" json:"serialNumber"`
AssetName string `gorm:"size:255" json:"assetName"`
@@ -46,6 +47,9 @@ func (p *ProductInventory) BeforeCreate(tx *gorm.DB) (err error) {
now := time.Now().UnixMilli()
p.ProductCode = normalizeProductCodeValue(p.ProductCode)
p.ProjectTypeCode = strings.TrimSpace(strings.ToLower(p.ProjectTypeCode))
if p.SuiteID != nil && *p.SuiteID == 0 {
p.SuiteID = nil
}
p.SuiteCode = strings.TrimSpace(p.SuiteCode)
p.SerialNumber = normalizeOptionalProductString(p.SerialNumber)
p.AssetName = strings.TrimSpace(p.AssetName)
@@ -66,6 +70,9 @@ func (p *ProductInventory) BeforeCreate(tx *gorm.DB) (err error) {
func (p *ProductInventory) BeforeUpdate(tx *gorm.DB) (err error) {
p.ProductCode = normalizeProductCodeValue(p.ProductCode)
p.ProjectTypeCode = strings.TrimSpace(strings.ToLower(p.ProjectTypeCode))
if p.SuiteID != nil && *p.SuiteID == 0 {
p.SuiteID = nil
}
p.SuiteCode = strings.TrimSpace(p.SuiteCode)
p.SerialNumber = normalizeOptionalProductString(p.SerialNumber)
p.AssetName = strings.TrimSpace(p.AssetName)
+114
View File
@@ -0,0 +1,114 @@
package models
import (
"errors"
"strings"
"time"
"gorm.io/gorm"
)
type ProductPrototype struct {
ID uint `gorm:"primaryKey" json:"id"`
Name string `gorm:"size:255;not null" json:"name"`
ProductCode string `gorm:"size:64;not null;index" json:"productCode"`
ProjectTypeCode string `gorm:"size:64;index" json:"projectTypeCode"`
AssetName string `gorm:"size:255" json:"assetName"`
Status string `gorm:"size:32;not null;default:'in_stock'" json:"status"`
RegionID *uint32 `gorm:"index" json:"regionId"`
StorageLocation string `gorm:"size:255" json:"storageLocation"`
ParameterValues string `gorm:"type:text" json:"parameterValues"`
Notes string `gorm:"size:1024" json:"notes"`
CreatedAt int64 `gorm:"not null" json:"created_at"`
UpdatedAt int64 `gorm:"not null" json:"updated_at"`
}
func (ProductPrototype) TableName() string {
return "product_prototypes"
}
func (p *ProductPrototype) BeforeCreate(tx *gorm.DB) (err error) {
now := time.Now().UnixMilli()
p.Name = strings.TrimSpace(p.Name)
p.ProductCode = normalizeProductCodeValue(p.ProductCode)
p.ProjectTypeCode = strings.TrimSpace(strings.ToLower(p.ProjectTypeCode))
p.AssetName = strings.TrimSpace(p.AssetName)
p.Status = string(normalizeProductInventoryStatus(ProductInventoryStatus(p.Status)))
if p.RegionID != nil && *p.RegionID == 0 {
p.RegionID = nil
}
p.StorageLocation = strings.TrimSpace(p.StorageLocation)
p.ParameterValues = normalizeJSONTextValue(p.ParameterValues)
p.Notes = strings.TrimSpace(p.Notes)
p.CreatedAt = now
p.UpdatedAt = now
return nil
}
func (p *ProductPrototype) BeforeUpdate(tx *gorm.DB) (err error) {
p.Name = strings.TrimSpace(p.Name)
p.ProductCode = normalizeProductCodeValue(p.ProductCode)
p.ProjectTypeCode = strings.TrimSpace(strings.ToLower(p.ProjectTypeCode))
p.AssetName = strings.TrimSpace(p.AssetName)
p.Status = string(normalizeProductInventoryStatus(ProductInventoryStatus(p.Status)))
if p.RegionID != nil && *p.RegionID == 0 {
p.RegionID = nil
}
p.StorageLocation = strings.TrimSpace(p.StorageLocation)
p.ParameterValues = normalizeJSONTextValue(p.ParameterValues)
p.Notes = strings.TrimSpace(p.Notes)
p.UpdatedAt = time.Now().UnixMilli()
return nil
}
func EnsureDefaultProductPrototypes(db *gorm.DB) error {
defaults := []ProductPrototype{
{
Name: "心率手环默认原型",
ProductCode: "collection_band",
ProjectTypeCode: "heartrate",
AssetName: "智能心率采集手环",
Status: string(ProductInventoryStatusInStock),
ParameterValues: mustJSON(map[string]interface{}{
"bandSize": "M",
"firmwareVersion": "default",
}),
Notes: "用于批量新增智能心率采集手环时复用通用参数",
},
{
Name: "50米手环默认原型",
ProductCode: "collection_band",
ProjectTypeCode: "run50",
AssetName: "50米往返跑手环",
Status: string(ProductInventoryStatusInStock),
ParameterValues: mustJSON(map[string]interface{}{
"bandSize": "M",
"firmwareVersion": "default",
}),
Notes: "用于50米往返跑手环的默认参数",
},
}
for _, item := range defaults {
var existing ProductPrototype
err := db.Where("name = ? AND product_code = ? AND project_type_code = ?", item.Name, item.ProductCode, item.ProjectTypeCode).First(&existing).Error
switch {
case err == nil:
existing.AssetName = item.AssetName
existing.Status = item.Status
existing.ParameterValues = item.ParameterValues
existing.Notes = item.Notes
if err := db.Save(&existing).Error; err != nil {
return err
}
case errors.Is(err, gorm.ErrRecordNotFound):
if err := db.Create(&item).Error; err != nil {
return err
}
default:
return err
}
}
return nil
}
+49
View File
@@ -0,0 +1,49 @@
package models
import (
"strings"
"time"
"gorm.io/gorm"
)
type ProductSuite struct {
ID uint `gorm:"primaryKey" json:"id"`
Code string `gorm:"size:128;not null;uniqueIndex" json:"code"`
Name string `gorm:"size:255;not null" json:"name"`
ProjectTypeCode string `gorm:"size:64;index" json:"projectTypeCode"`
RegionID *uint32 `gorm:"index" json:"regionId"`
SoldTargetType string `gorm:"size:64;index" json:"soldTargetType"`
SoldTargetName string `gorm:"size:255" json:"soldTargetName"`
Notes string `gorm:"size:1024" json:"notes"`
CreatedAt int64 `gorm:"not null" json:"created_at"`
UpdatedAt int64 `gorm:"not null" json:"updated_at"`
}
func (ProductSuite) TableName() string {
return "product_suites"
}
func (p *ProductSuite) BeforeCreate(tx *gorm.DB) (err error) {
now := time.Now().UnixMilli()
p.Code = strings.TrimSpace(p.Code)
p.Name = strings.TrimSpace(p.Name)
p.ProjectTypeCode = strings.TrimSpace(strings.ToLower(p.ProjectTypeCode))
p.SoldTargetType = strings.TrimSpace(strings.ToLower(p.SoldTargetType))
p.SoldTargetName = strings.TrimSpace(p.SoldTargetName)
p.Notes = strings.TrimSpace(p.Notes)
p.CreatedAt = now
p.UpdatedAt = now
return nil
}
func (p *ProductSuite) BeforeUpdate(tx *gorm.DB) (err error) {
p.Code = strings.TrimSpace(p.Code)
p.Name = strings.TrimSpace(p.Name)
p.ProjectTypeCode = strings.TrimSpace(strings.ToLower(p.ProjectTypeCode))
p.SoldTargetType = strings.TrimSpace(strings.ToLower(p.SoldTargetType))
p.SoldTargetName = strings.TrimSpace(p.SoldTargetName)
p.Notes = strings.TrimSpace(p.Notes)
p.UpdatedAt = time.Now().UnixMilli()
return nil
}