- Add price_updated_at field to qt_configurations table to track when prices were last updated - Add RefreshPrices() method in configuration service to update all component prices with current values from database - Add POST /api/configs/:uuid/refresh-prices API endpoint for price updates - Add "Refresh Prices" button in configurator UI next to Save button - Display last price update timestamp in human-readable format (e.g., "5 min ago", "2 hours ago") - Create migration 004_add_price_updated_at.sql for database schema update - Update CLAUDE.md documentation with new API endpoint and schema changes - Add MIGRATION_PRICE_REFRESH.md with detailed migration instructions Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
78 lines
2.3 KiB
Go
78 lines
2.3 KiB
Go
package models
|
|
|
|
import (
|
|
"database/sql/driver"
|
|
"encoding/json"
|
|
"errors"
|
|
"time"
|
|
)
|
|
|
|
type ConfigItem struct {
|
|
LotName string `json:"lot_name"`
|
|
Quantity int `json:"quantity"`
|
|
UnitPrice float64 `json:"unit_price"`
|
|
}
|
|
|
|
type ConfigItems []ConfigItem
|
|
|
|
func (c ConfigItems) Value() (driver.Value, error) {
|
|
return json.Marshal(c)
|
|
}
|
|
|
|
func (c *ConfigItems) Scan(value interface{}) error {
|
|
if value == nil {
|
|
*c = make(ConfigItems, 0)
|
|
return nil
|
|
}
|
|
bytes, ok := value.([]byte)
|
|
if !ok {
|
|
return errors.New("type assertion to []byte failed")
|
|
}
|
|
return json.Unmarshal(bytes, c)
|
|
}
|
|
|
|
func (c ConfigItems) Total() float64 {
|
|
var total float64
|
|
for _, item := range c {
|
|
total += item.UnitPrice * float64(item.Quantity)
|
|
}
|
|
return total
|
|
}
|
|
|
|
type Configuration struct {
|
|
ID uint `gorm:"primaryKey;autoIncrement" json:"id"`
|
|
UUID string `gorm:"size:36;uniqueIndex;not null" json:"uuid"`
|
|
UserID uint `gorm:"not null" json:"user_id"`
|
|
Name string `gorm:"size:200;not null" json:"name"`
|
|
Items ConfigItems `gorm:"type:json;not null" json:"items"`
|
|
TotalPrice *float64 `gorm:"type:decimal(12,2)" json:"total_price"`
|
|
CustomPrice *float64 `gorm:"type:decimal(12,2)" json:"custom_price"`
|
|
Notes string `gorm:"type:text" json:"notes"`
|
|
IsTemplate bool `gorm:"default:false" json:"is_template"`
|
|
ServerCount int `gorm:"default:1" json:"server_count"`
|
|
PriceUpdatedAt *time.Time `gorm:"type:timestamp" json:"price_updated_at,omitempty"`
|
|
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
|
|
|
|
User *User `gorm:"foreignKey:UserID" json:"user,omitempty"`
|
|
}
|
|
|
|
func (Configuration) TableName() string {
|
|
return "qt_configurations"
|
|
}
|
|
|
|
type PriceOverride struct {
|
|
ID uint `gorm:"primaryKey;autoIncrement" json:"id"`
|
|
LotName string `gorm:"size:255;not null" json:"lot_name"`
|
|
Price float64 `gorm:"type:decimal(12,2);not null" json:"price"`
|
|
ValidFrom time.Time `gorm:"type:date;not null" json:"valid_from"`
|
|
ValidUntil *time.Time `gorm:"type:date" json:"valid_until"`
|
|
Reason string `gorm:"type:text" json:"reason"`
|
|
CreatedBy uint `gorm:"not null" json:"created_by"`
|
|
|
|
Creator *User `gorm:"foreignKey:CreatedBy" json:"creator,omitempty"`
|
|
}
|
|
|
|
func (PriceOverride) TableName() string {
|
|
return "qt_price_overrides"
|
|
}
|