Update pricing handler counts and defaults

This commit is contained in:
Mikhail Chusavitin
2026-02-18 10:31:35 +03:00
parent c939ce18ad
commit 50d1e281a5

View File

@@ -211,13 +211,52 @@ func (h *PricingHandler) ListComponents(c *gin.Context) {
return
}
// Get quote counts
// Get all lot names for meta expansion
var allLotNames []string
h.db.Model(&models.LotMetadata{}).Pluck("lot_name", &allLotNames)
// Build per-component source lots for quote counts
componentSources := make(map[string][]string, len(components))
uniqueLots := make(map[string]struct{})
lotNames := make([]string, len(components))
for i, comp := range components {
lotNames[i] = comp.LotName
var sourceLots []string
if strings.TrimSpace(comp.MetaPrices) != "" {
sourceLots = expandMetaPricesWithCache(comp.MetaPrices, comp.LotName, allLotNames)
} else {
sourceLots = []string{comp.LotName}
}
componentSources[comp.LotName] = sourceLots
for _, ln := range sourceLots {
if ln == "" {
continue
}
uniqueLots[ln] = struct{}{}
}
}
counts, _ := h.priceRepo.GetQuoteCounts(lotNames)
// Fetch quote counts for all source lots in one query
counts := map[string]int64{}
if len(uniqueLots) > 0 {
allSources := make([]string, 0, len(uniqueLots))
for ln := range uniqueLots {
allSources = append(allSources, ln)
}
type Result struct {
Lot string
Count int64
}
var results []Result
_ = h.db.Model(&models.LotLog{}).
Select("lot, COUNT(*) as count").
Where("lot IN ?", allSources).
Group("lot").
Scan(&results).Error
for _, r := range results {
counts[r.Lot] = r.Count
}
}
// Get meta usage information
metaUsage := h.getMetaUsageMap(lotNames)
@@ -225,9 +264,14 @@ func (h *PricingHandler) ListComponents(c *gin.Context) {
// Combine components with counts
result := make([]ComponentWithCount, len(components))
for i, comp := range components {
sourceLots := componentSources[comp.LotName]
var quoteCount int64
for _, ln := range sourceLots {
quoteCount += counts[ln]
}
result[i] = ComponentWithCount{
LotMetadata: comp,
QuoteCount: counts[comp.LotName],
QuoteCount: quoteCount,
UsedInMeta: metaUsage[comp.LotName],
}
}
@@ -522,6 +566,8 @@ func (h *PricingHandler) RecalculateAll(c *gin.Context) {
return
}
force := c.Query("force") == "1" || strings.EqualFold(c.Query("force"), "true")
taskID := h.taskManager.Submit(tasks.TaskTypeRecalculate, func(ctx context.Context, progressCb func(int, string)) (map[string]interface{}, error) {
// Get all components with their settings
var components []models.LotMetadata
@@ -554,7 +600,7 @@ func (h *PricingHandler) RecalculateAll(c *gin.Context) {
}
// Process components individually to respect their settings
var updated, skipped, manual, unchanged, errors int
var updated, skipped, manual, unchanged, errors, noPeriodData int
now := time.Now()
for i, comp := range components {
@@ -586,7 +632,7 @@ func (h *PricingHandler) RecalculateAll(c *gin.Context) {
}
// Check if there are new quotes since last update (using cached dates)
if comp.PriceUpdatedAt != nil {
if !force && comp.PriceUpdatedAt != nil {
hasNewData := false
for _, lot := range sourceLots {
if latestDate, ok := lotLatestDate[lot]; ok {
@@ -609,8 +655,10 @@ func (h *PricingHandler) RecalculateAll(c *gin.Context) {
goto sendProgress
}
noPeriodForComp := false
// If no prices in period, try all time
if len(prices) == 0 && periodDays > 0 {
noPeriodForComp = true
prices, err = h.queryMultipleLotPrices(sourceLots, 0)
if err != nil {
errors++
@@ -619,9 +667,15 @@ func (h *PricingHandler) RecalculateAll(c *gin.Context) {
}
if len(prices) == 0 {
if noPeriodForComp {
noPeriodData++
}
skipped++
goto sendProgress
}
if noPeriodForComp {
noPeriodData++
}
// Calculate price based on method
var basePrice float64
@@ -676,15 +730,16 @@ func (h *PricingHandler) RecalculateAll(c *gin.Context) {
h.statsRepo.UpdatePopularityScores()
// Send final completion message
progressCb(100, fmt.Sprintf("Пересчёт завершён: обновлено %d из %d компонентов", updated, total))
progressCb(100, fmt.Sprintf("Пересчёт завершён: обновлено %d из %d, без данных за период: %d", updated, total, noPeriodData))
return map[string]interface{}{
"updated": updated,
"skipped": skipped,
"manual": manual,
"unchanged": unchanged,
"errors": errors,
"total": total,
"updated": updated,
"skipped": skipped,
"manual": manual,
"unchanged": unchanged,
"errors": errors,
"total": total,
"no_period_data": noPeriodData,
}, nil
})
@@ -1456,8 +1511,7 @@ func (h *PricingHandler) CreateLot(c *gin.Context) {
categoryCode := strings.ToUpper(strings.TrimSpace(req.Category))
if categoryCode == "" {
parsedCategory, _ := services.ParsePartNumber(lotName)
categoryCode = strings.ToUpper(strings.TrimSpace(parsedCategory))
categoryCode = models.DefaultLotCategoryCode
}
if len(categoryCode) > 20 {
c.JSON(http.StatusBadRequest, gin.H{"error": "category too long (max 20)"})