Apply remaining pricelist and local-first updates

This commit is contained in:
Mikhail Chusavitin
2026-02-06 13:01:40 +03:00
parent 8e5c4f5a7c
commit 80ec7bc6b8
19 changed files with 767 additions and 30 deletions

View File

@@ -24,6 +24,7 @@ type ConfigurationService struct {
configRepo *repository.ConfigurationRepository
projectRepo *repository.ProjectRepository
componentRepo *repository.ComponentRepository
pricelistRepo *repository.PricelistRepository
quoteService *QuoteService
}
@@ -31,12 +32,14 @@ func NewConfigurationService(
configRepo *repository.ConfigurationRepository,
projectRepo *repository.ProjectRepository,
componentRepo *repository.ComponentRepository,
pricelistRepo *repository.PricelistRepository,
quoteService *QuoteService,
) *ConfigurationService {
return &ConfigurationService{
configRepo: configRepo,
projectRepo: projectRepo,
componentRepo: componentRepo,
pricelistRepo: pricelistRepo,
quoteService: quoteService,
}
}
@@ -49,6 +52,7 @@ type CreateConfigRequest struct {
Notes string `json:"notes"`
IsTemplate bool `json:"is_template"`
ServerCount int `json:"server_count"`
PricelistID *uint `json:"pricelist_id,omitempty"`
}
func (s *ConfigurationService) Create(ownerUsername string, req *CreateConfigRequest) (*models.Configuration, error) {
@@ -56,6 +60,10 @@ func (s *ConfigurationService) Create(ownerUsername string, req *CreateConfigReq
if err != nil {
return nil, err
}
pricelistID, err := s.resolvePricelistID(req.PricelistID)
if err != nil {
return nil, err
}
total := req.Items.Total()
@@ -75,6 +83,7 @@ func (s *ConfigurationService) Create(ownerUsername string, req *CreateConfigReq
Notes: req.Notes,
IsTemplate: req.IsTemplate,
ServerCount: req.ServerCount,
PricelistID: pricelistID,
}
if err := s.configRepo.Create(config); err != nil {
@@ -115,6 +124,10 @@ func (s *ConfigurationService) Update(uuid string, ownerUsername string, req *Cr
if err != nil {
return nil, err
}
pricelistID, err := s.resolvePricelistID(req.PricelistID)
if err != nil {
return nil, err
}
total := req.Items.Total()
@@ -131,6 +144,7 @@ func (s *ConfigurationService) Update(uuid string, ownerUsername string, req *Cr
config.Notes = req.Notes
config.IsTemplate = req.IsTemplate
config.ServerCount = req.ServerCount
config.PricelistID = pricelistID
if err := s.configRepo.Update(config); err != nil {
return nil, err
@@ -207,6 +221,7 @@ func (s *ConfigurationService) CloneToProject(configUUID string, ownerUsername s
Notes: original.Notes,
IsTemplate: false, // Clone is never a template
ServerCount: original.ServerCount,
PricelistID: original.PricelistID,
}
if err := s.configRepo.Create(clone); err != nil {
@@ -261,6 +276,10 @@ func (s *ConfigurationService) UpdateNoAuth(uuid string, req *CreateConfigReques
if err != nil {
return nil, err
}
pricelistID, err := s.resolvePricelistID(req.PricelistID)
if err != nil {
return nil, err
}
total := req.Items.Total()
if req.ServerCount > 1 {
@@ -275,6 +294,7 @@ func (s *ConfigurationService) UpdateNoAuth(uuid string, req *CreateConfigReques
config.Notes = req.Notes
config.IsTemplate = req.IsTemplate
config.ServerCount = req.ServerCount
config.PricelistID = pricelistID
if err := s.configRepo.Update(config); err != nil {
return nil, err
@@ -341,6 +361,7 @@ func (s *ConfigurationService) CloneNoAuthToProject(configUUID string, newName s
Notes: original.Notes,
IsTemplate: false,
ServerCount: original.ServerCount,
PricelistID: original.PricelistID,
}
if err := s.configRepo.Create(clone); err != nil {
@@ -370,6 +391,23 @@ func (s *ConfigurationService) resolveProjectUUID(ownerUsername string, projectU
return &project.UUID, nil
}
func (s *ConfigurationService) resolvePricelistID(pricelistID *uint) (*uint, error) {
if s.pricelistRepo == nil {
return pricelistID, nil
}
if pricelistID != nil && *pricelistID > 0 {
if _, err := s.pricelistRepo.GetByID(*pricelistID); err != nil {
return nil, err
}
return pricelistID, nil
}
latest, err := s.pricelistRepo.GetLatestActive()
if err != nil {
return nil, nil
}
return &latest.ID, nil
}
// RefreshPricesNoAuth refreshes prices without ownership check
func (s *ConfigurationService) RefreshPricesNoAuth(uuid string) (*models.Configuration, error) {
config, err := s.configRepo.GetByUUID(uuid)
@@ -377,8 +415,30 @@ func (s *ConfigurationService) RefreshPricesNoAuth(uuid string) (*models.Configu
return nil, ErrConfigNotFound
}
var latestPricelistID *uint
if s.pricelistRepo != nil {
if pl, err := s.pricelistRepo.GetLatestActive(); err == nil {
latestPricelistID = &pl.ID
}
}
updatedItems := make(models.ConfigItems, len(config.Items))
for i, item := range config.Items {
if latestPricelistID != nil {
if price, err := s.pricelistRepo.GetPriceForLot(*latestPricelistID, item.LotName); err == nil && price > 0 {
updatedItems[i] = models.ConfigItem{
LotName: item.LotName,
Quantity: item.Quantity,
UnitPrice: price,
}
continue
}
}
if s.componentRepo == nil {
updatedItems[i] = item
continue
}
metadata, err := s.componentRepo.GetByLotName(item.LotName)
if err != nil || metadata.CurrentPrice == nil {
updatedItems[i] = item
@@ -399,6 +459,9 @@ func (s *ConfigurationService) RefreshPricesNoAuth(uuid string) (*models.Configu
}
config.TotalPrice = &total
if latestPricelistID != nil {
config.PricelistID = latestPricelistID
}
now := time.Now()
config.PriceUpdatedAt = &now
@@ -432,10 +495,32 @@ func (s *ConfigurationService) RefreshPrices(uuid string, ownerUsername string)
return nil, ErrConfigForbidden
}
var latestPricelistID *uint
if s.pricelistRepo != nil {
if pl, err := s.pricelistRepo.GetLatestActive(); err == nil {
latestPricelistID = &pl.ID
}
}
// Update prices for all items
updatedItems := make(models.ConfigItems, len(config.Items))
for i, item := range config.Items {
if latestPricelistID != nil {
if price, err := s.pricelistRepo.GetPriceForLot(*latestPricelistID, item.LotName); err == nil && price > 0 {
updatedItems[i] = models.ConfigItem{
LotName: item.LotName,
Quantity: item.Quantity,
UnitPrice: price,
}
continue
}
}
// Get current component price
if s.componentRepo == nil {
updatedItems[i] = item
continue
}
metadata, err := s.componentRepo.GetByLotName(item.LotName)
if err != nil || metadata.CurrentPrice == nil {
// Keep original item if component not found or no price available
@@ -461,6 +546,9 @@ func (s *ConfigurationService) RefreshPrices(uuid string, ownerUsername string)
}
config.TotalPrice = &total
if latestPricelistID != nil {
config.PricelistID = latestPricelistID
}
// Set price update timestamp
now := time.Now()