Deduplicate configuration revisions and update revisions UI

This commit is contained in:
2026-02-19 14:09:00 +03:00
parent 71f73e2f1d
commit cbaeafa9c8
10 changed files with 839 additions and 188 deletions

View File

@@ -3,6 +3,7 @@ package localdb
import (
"encoding/json"
"fmt"
"sort"
"time"
)
@@ -94,3 +95,51 @@ func DecodeConfigurationSnapshot(data string) (*LocalConfiguration, error) {
OriginalUsername: snapshot.OriginalUsername,
}, nil
}
type configurationSpecPriceFingerprint struct {
Items []configurationSpecPriceFingerprintItem `json:"items"`
ServerCount int `json:"server_count"`
TotalPrice *float64 `json:"total_price,omitempty"`
CustomPrice *float64 `json:"custom_price,omitempty"`
}
type configurationSpecPriceFingerprintItem struct {
LotName string `json:"lot_name"`
Quantity int `json:"quantity"`
UnitPrice float64 `json:"unit_price"`
}
// BuildConfigurationSpecPriceFingerprint returns a stable JSON key based on
// spec + price fields only, used for revision deduplication.
func BuildConfigurationSpecPriceFingerprint(localCfg *LocalConfiguration) (string, error) {
items := make([]configurationSpecPriceFingerprintItem, 0, len(localCfg.Items))
for _, item := range localCfg.Items {
items = append(items, configurationSpecPriceFingerprintItem{
LotName: item.LotName,
Quantity: item.Quantity,
UnitPrice: item.UnitPrice,
})
}
sort.Slice(items, func(i, j int) bool {
if items[i].LotName != items[j].LotName {
return items[i].LotName < items[j].LotName
}
if items[i].Quantity != items[j].Quantity {
return items[i].Quantity < items[j].Quantity
}
return items[i].UnitPrice < items[j].UnitPrice
})
payload := configurationSpecPriceFingerprint{
Items: items,
ServerCount: localCfg.ServerCount,
TotalPrice: localCfg.TotalPrice,
CustomPrice: localCfg.CustomPrice,
}
raw, err := json.Marshal(payload)
if err != nil {
return "", fmt.Errorf("marshal spec+price fingerprint: %w", err)
}
return string(raw), nil
}