package models import ( "strings" "time" "gorm.io/gorm" ) type ProductInventoryStatus string const ( ProductInventoryStatusInStock ProductInventoryStatus = "in_stock" ProductInventoryStatusSold ProductInventoryStatus = "sold" ProductInventoryStatusMaintenance ProductInventoryStatus = "maintenance" ProductInventoryStatusRetired ProductInventoryStatus = "retired" ) 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"` SuiteCode string `gorm:"size:128;index" json:"suiteCode"` SerialNumber *string `gorm:"size:128;uniqueIndex" json:"serialNumber"` AssetName string `gorm:"size:255" json:"assetName"` Status ProductInventoryStatus `gorm:"size:32;not null;default:'in_stock';index" json:"status"` RegionID *uint32 `gorm:"index" json:"regionId"` StorageLocation string `gorm:"size:255" json:"storageLocation"` SoldTargetType string `gorm:"size:64;index" json:"soldTargetType"` SoldTargetName string `gorm:"size:255" json:"soldTargetName"` SoldTo string `gorm:"size:255" json:"soldTo"` SoldAt *time.Time `json:"soldAt"` ParameterValues string `gorm:"type:text" json:"parameterValues"` SourceType string `gorm:"size:64;index" json:"sourceType"` SourceRef string `gorm:"size:128;index" json:"sourceRef"` Notes string `gorm:"size:1024" json:"notes"` CreatedAt int64 `gorm:"not null" json:"created_at"` UpdatedAt int64 `gorm:"not null" json:"updated_at"` } func (ProductInventory) TableName() string { return "product_inventories" } 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)) p.SuiteCode = strings.TrimSpace(p.SuiteCode) p.SerialNumber = normalizeOptionalProductString(p.SerialNumber) p.AssetName = strings.TrimSpace(p.AssetName) p.StorageLocation = strings.TrimSpace(p.StorageLocation) p.SoldTargetType = strings.TrimSpace(strings.ToLower(p.SoldTargetType)) p.SoldTargetName = strings.TrimSpace(p.SoldTargetName) p.SoldTo = strings.TrimSpace(p.SoldTo) p.ParameterValues = normalizeJSONTextValue(p.ParameterValues) p.SourceType = strings.TrimSpace(strings.ToLower(p.SourceType)) p.SourceRef = strings.TrimSpace(p.SourceRef) p.Notes = strings.TrimSpace(p.Notes) p.Status = normalizeProductInventoryStatus(p.Status) p.CreatedAt = now p.UpdatedAt = now return nil } func (p *ProductInventory) BeforeUpdate(tx *gorm.DB) (err error) { p.ProductCode = normalizeProductCodeValue(p.ProductCode) p.ProjectTypeCode = strings.TrimSpace(strings.ToLower(p.ProjectTypeCode)) p.SuiteCode = strings.TrimSpace(p.SuiteCode) p.SerialNumber = normalizeOptionalProductString(p.SerialNumber) p.AssetName = strings.TrimSpace(p.AssetName) p.StorageLocation = strings.TrimSpace(p.StorageLocation) p.SoldTargetType = strings.TrimSpace(strings.ToLower(p.SoldTargetType)) p.SoldTargetName = strings.TrimSpace(p.SoldTargetName) p.SoldTo = strings.TrimSpace(p.SoldTo) p.ParameterValues = normalizeJSONTextValue(p.ParameterValues) p.SourceType = strings.TrimSpace(strings.ToLower(p.SourceType)) p.SourceRef = strings.TrimSpace(p.SourceRef) p.Notes = strings.TrimSpace(p.Notes) p.Status = normalizeProductInventoryStatus(p.Status) p.UpdatedAt = time.Now().UnixMilli() return nil } func normalizeOptionalProductString(value *string) *string { if value == nil { return nil } trimmed := strings.TrimSpace(*value) if trimmed == "" { return nil } return &trimmed } func normalizeProductInventoryStatus(status ProductInventoryStatus) ProductInventoryStatus { switch ProductInventoryStatus(strings.TrimSpace(strings.ToLower(string(status)))) { case ProductInventoryStatusSold: return ProductInventoryStatusSold case ProductInventoryStatusMaintenance: return ProductInventoryStatusMaintenance case ProductInventoryStatusRetired: return ProductInventoryStatusRetired default: return ProductInventoryStatusInStock } }