6.15.4: Подзадачи в драфтах авто-выполнения
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m28s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m28s
This commit is contained in:
@@ -3514,6 +3514,123 @@ func (a *App) getAutoCompleteDraftEntries(userID int) ([]TodayEntry, error) {
|
|||||||
entryText = taskName
|
entryText = taskName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Вычисляем следующий свободный индекс для нод подзадач
|
||||||
|
nextNodeIndex := 0
|
||||||
|
for _, node := range nodes {
|
||||||
|
if node.Index >= nextNodeIndex {
|
||||||
|
nextNodeIndex = node.Index + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Получаем checked подзадачи из task_draft_subtasks для этого драфта
|
||||||
|
subtaskRows, err := a.DB.Query(`
|
||||||
|
SELECT t.id, t.name, COALESCE(t.reward_message, ''), t.progression_base
|
||||||
|
FROM task_draft_subtasks tds
|
||||||
|
JOIN task_drafts td ON tds.task_draft_id = td.id
|
||||||
|
JOIN tasks t ON tds.subtask_id = t.id
|
||||||
|
WHERE td.task_id = $1 AND td.user_id = $2 AND t.deleted = FALSE
|
||||||
|
`, taskID, userID)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error querying draft subtasks for task %d: %v", taskID, err)
|
||||||
|
} else {
|
||||||
|
for subtaskRows.Next() {
|
||||||
|
var subtaskID int
|
||||||
|
var subtaskName string
|
||||||
|
var subtaskRewardMsg string
|
||||||
|
var subtaskProgressionBase sql.NullFloat64
|
||||||
|
|
||||||
|
if err := subtaskRows.Scan(&subtaskID, &subtaskName, &subtaskRewardMsg, &subtaskProgressionBase); err != nil {
|
||||||
|
log.Printf("Error scanning subtask row for draft: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Пропускаем подзадачи без reward_message
|
||||||
|
if subtaskRewardMsg == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Получаем ноды подзадачи
|
||||||
|
subtaskRewardRows, err := a.DB.Query(`
|
||||||
|
SELECT rc.position, p.name AS project_name, rc.value, rc.use_progression
|
||||||
|
FROM reward_configs rc
|
||||||
|
JOIN projects p ON rc.project_id = p.id
|
||||||
|
WHERE rc.task_id = $1
|
||||||
|
ORDER BY rc.position
|
||||||
|
`, subtaskID)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error querying subtask rewards for draft subtask %d: %v", subtaskID, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
type subtaskRewardEntry struct {
|
||||||
|
position int
|
||||||
|
projectName string
|
||||||
|
rewardValue float64
|
||||||
|
useProgression bool
|
||||||
|
}
|
||||||
|
subtaskRewards := make([]subtaskRewardEntry, 0)
|
||||||
|
for subtaskRewardRows.Next() {
|
||||||
|
var sre subtaskRewardEntry
|
||||||
|
if err := subtaskRewardRows.Scan(&sre.position, &sre.projectName, &sre.rewardValue, &sre.useProgression); err != nil {
|
||||||
|
log.Printf("Error scanning subtask reward row for draft: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
subtaskRewards = append(subtaskRewards, sre)
|
||||||
|
}
|
||||||
|
subtaskRewardRows.Close()
|
||||||
|
|
||||||
|
// Определяем progression base для подзадачи
|
||||||
|
var subtaskProgressionBasePtr *float64
|
||||||
|
if subtaskProgressionBase.Valid {
|
||||||
|
subtaskProgressionBasePtr = &subtaskProgressionBase.Float64
|
||||||
|
} else if progressionBase.Valid {
|
||||||
|
subtaskProgressionBasePtr = &progressionBase.Float64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Строим map позиция → новый глобальный индекс и добавляем ноды
|
||||||
|
positionToIndex := make(map[int]int)
|
||||||
|
for _, sre := range subtaskRewards {
|
||||||
|
reward := Reward{
|
||||||
|
Value: sre.rewardValue,
|
||||||
|
UseProgression: sre.useProgression,
|
||||||
|
}
|
||||||
|
score := calculateRewardScore(reward, progressionValuePtr, subtaskProgressionBasePtr)
|
||||||
|
positionToIndex[sre.position] = nextNodeIndex
|
||||||
|
nodes = append(nodes, TodayEntryNode{
|
||||||
|
ProjectName: sre.projectName,
|
||||||
|
Score: score,
|
||||||
|
Index: nextNodeIndex,
|
||||||
|
})
|
||||||
|
nextNodeIndex++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Переписываем reward_message подзадачи, заменяя $position на ${globalIndex}
|
||||||
|
subtaskText := subtaskRewardMsg
|
||||||
|
// Заменяем $subtaskName
|
||||||
|
subtaskText = strings.ReplaceAll(subtaskText, "$subtaskName", subtaskName)
|
||||||
|
// Заменяем $name
|
||||||
|
subtaskText = strings.ReplaceAll(subtaskText, "$name", taskName)
|
||||||
|
// Заменяем ${pos} и $pos на ${globalIndex}
|
||||||
|
for pos, globalIdx := range positionToIndex {
|
||||||
|
newPlaceholder := fmt.Sprintf("${%d}", globalIdx)
|
||||||
|
subtaskText = strings.ReplaceAll(subtaskText, fmt.Sprintf("${%d}", pos), newPlaceholder)
|
||||||
|
}
|
||||||
|
for i := 99; i >= 0; i-- {
|
||||||
|
if globalIdx, ok := positionToIndex[i]; ok {
|
||||||
|
newPlaceholder := fmt.Sprintf("${%d}", globalIdx)
|
||||||
|
re := regexp.MustCompile(fmt.Sprintf(`\$%d(\D|$)`, i))
|
||||||
|
subtaskText = re.ReplaceAllStringFunc(subtaskText, func(match string) string {
|
||||||
|
suffix := []rune(match)[len([]rune(fmt.Sprintf("$%d", i))):]
|
||||||
|
return newPlaceholder + string(suffix)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entryText += "\n + " + subtaskText
|
||||||
|
}
|
||||||
|
subtaskRows.Close()
|
||||||
|
}
|
||||||
|
|
||||||
taskIDCopy := taskID
|
taskIDCopy := taskID
|
||||||
entries = append(entries, TodayEntry{
|
entries = append(entries, TodayEntry{
|
||||||
IsDraft: true,
|
IsDraft: true,
|
||||||
|
|||||||
Binary file not shown.
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "play-life-web",
|
"name": "play-life-web",
|
||||||
"version": "6.15.3",
|
"version": "6.15.4",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
Reference in New Issue
Block a user