Update pricing handler counts and defaults
This commit is contained in:
@@ -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)"})
|
||||
|
||||
Reference in New Issue
Block a user