4.3.0: Автовыполнение задач в конце дня
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m11s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m11s
This commit is contained in:
@@ -232,6 +232,7 @@ type Task struct {
|
||||
ProjectNames []string `json:"project_names"`
|
||||
SubtasksCount int `json:"subtasks_count"`
|
||||
HasProgression bool `json:"has_progression"`
|
||||
AutoComplete bool `json:"auto_complete"`
|
||||
}
|
||||
|
||||
type Reward struct {
|
||||
@@ -6567,8 +6568,10 @@ func (a *App) getTasksHandler(w http.ResponseWriter, r *http.Request) {
|
||||
JOIN projects p ON rc.project_id = p.id
|
||||
WHERE st.parent_task_id = t.id AND st.deleted = FALSE),
|
||||
ARRAY[]::text[]
|
||||
) as subtask_project_names
|
||||
) as subtask_project_names,
|
||||
COALESCE(td.auto_complete, FALSE) as auto_complete
|
||||
FROM tasks t
|
||||
LEFT JOIN task_drafts td ON td.task_id = t.id AND td.user_id = $1
|
||||
WHERE t.user_id = $1 AND t.parent_task_id IS NULL AND t.deleted = FALSE
|
||||
ORDER BY
|
||||
CASE WHEN t.last_completed_at IS NULL OR t.last_completed_at::date < CURRENT_DATE THEN 0 ELSE 1 END,
|
||||
@@ -6596,6 +6599,7 @@ func (a *App) getTasksHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var rewardPolicy sql.NullString
|
||||
var projectNames pq.StringArray
|
||||
var subtaskProjectNames pq.StringArray
|
||||
var autoComplete bool
|
||||
|
||||
err := rows.Scan(
|
||||
&task.ID,
|
||||
@@ -6612,6 +6616,7 @@ func (a *App) getTasksHandler(w http.ResponseWriter, r *http.Request) {
|
||||
&task.SubtasksCount,
|
||||
&projectNames,
|
||||
&subtaskProjectNames,
|
||||
&autoComplete,
|
||||
)
|
||||
if err != nil {
|
||||
log.Printf("Error scanning task: %v", err)
|
||||
@@ -6647,6 +6652,7 @@ func (a *App) getTasksHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if rewardPolicy.Valid {
|
||||
task.RewardPolicy = &rewardPolicy.String
|
||||
}
|
||||
task.AutoComplete = autoComplete
|
||||
|
||||
// Объединяем проекты из основной задачи и подзадач
|
||||
allProjects := make(map[string]bool)
|
||||
@@ -6894,12 +6900,86 @@ func (a *App) getTaskDetailHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// Инициализируем auto_complete значением по умолчанию
|
||||
task.AutoComplete = false
|
||||
|
||||
// Загружаем данные из драфта, если он существует
|
||||
var draftProgressionValue sql.NullFloat64
|
||||
var draftAutoComplete sql.NullBool
|
||||
var draftProgressionValuePtr *float64
|
||||
var draftSubtasks []DraftSubtask
|
||||
err = a.DB.QueryRow(`
|
||||
SELECT progression_value, auto_complete
|
||||
FROM task_drafts
|
||||
WHERE task_id = $1 AND user_id = $2
|
||||
`, taskID, userID).Scan(&draftProgressionValue, &draftAutoComplete)
|
||||
|
||||
if err == nil {
|
||||
// Драфт существует, загружаем данные
|
||||
if draftProgressionValue.Valid {
|
||||
draftProgressionValuePtr = &draftProgressionValue.Float64
|
||||
}
|
||||
// Устанавливаем auto_complete из драфта (если Valid, иначе остается false)
|
||||
if draftAutoComplete.Valid {
|
||||
task.AutoComplete = draftAutoComplete.Bool
|
||||
log.Printf("Task %d: auto_complete set to %v from draft", taskID, task.AutoComplete)
|
||||
} else {
|
||||
log.Printf("Task %d: draft exists but auto_complete is NULL, keeping default false", taskID)
|
||||
}
|
||||
|
||||
// Загружаем подзадачи из драфта
|
||||
draftSubtaskRows, err := a.DB.Query(`
|
||||
SELECT subtask_id
|
||||
FROM task_draft_subtasks
|
||||
WHERE task_draft_id = (SELECT id FROM task_drafts WHERE task_id = $1 AND user_id = $2)
|
||||
`, taskID, userID)
|
||||
if err == nil {
|
||||
defer draftSubtaskRows.Close()
|
||||
draftSubtasks = make([]DraftSubtask, 0)
|
||||
validSubtaskIDs := make(map[int]bool)
|
||||
// Создаем map валидных подзадач для фильтрации
|
||||
for _, subtask := range subtasks {
|
||||
validSubtaskIDs[subtask.Task.ID] = true
|
||||
}
|
||||
|
||||
for draftSubtaskRows.Next() {
|
||||
var subtaskID int
|
||||
if err := draftSubtaskRows.Scan(&subtaskID); err == nil {
|
||||
// Игнорируем подзадачи, которых больше нет в основной задаче
|
||||
if validSubtaskIDs[subtaskID] {
|
||||
draftSubtasks = append(draftSubtasks, DraftSubtask{
|
||||
SubtaskID: subtaskID,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if err != sql.ErrNoRows {
|
||||
log.Printf("Error loading draft subtasks for task %d: %v", taskID, err)
|
||||
}
|
||||
} else if err != sql.ErrNoRows {
|
||||
log.Printf("Error loading draft for task %d: %v", taskID, err)
|
||||
} else {
|
||||
log.Printf("Task %d: no draft found, auto_complete remains false", taskID)
|
||||
}
|
||||
// Если драфта нет (err == sql.ErrNoRows), auto_complete остается false
|
||||
log.Printf("Task %d: final auto_complete value = %v", taskID, task.AutoComplete)
|
||||
|
||||
response := TaskDetail{
|
||||
Task: task,
|
||||
Rewards: rewards,
|
||||
Subtasks: subtasks,
|
||||
}
|
||||
|
||||
// Устанавливаем DraftProgressionValue если он был загружен
|
||||
if draftProgressionValuePtr != nil {
|
||||
response.DraftProgressionValue = draftProgressionValuePtr
|
||||
}
|
||||
|
||||
// Устанавливаем DraftSubtasks если они были загружены
|
||||
if len(draftSubtasks) > 0 {
|
||||
response.DraftSubtasks = draftSubtasks
|
||||
}
|
||||
|
||||
// Если задача связана с wishlist, загружаем базовую информацию о wishlist
|
||||
if wishlistID.Valid {
|
||||
var wishlistName string
|
||||
@@ -6926,56 +7006,6 @@ func (a *App) getTaskDetailHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// Загружаем данные из драфта, если он существует
|
||||
var draftProgressionValue sql.NullFloat64
|
||||
err = a.DB.QueryRow(`
|
||||
SELECT progression_value
|
||||
FROM task_drafts
|
||||
WHERE task_id = $1 AND user_id = $2
|
||||
`, taskID, userID).Scan(&draftProgressionValue)
|
||||
|
||||
if err == nil {
|
||||
// Драфт существует, загружаем данные
|
||||
if draftProgressionValue.Valid {
|
||||
response.DraftProgressionValue = &draftProgressionValue.Float64
|
||||
}
|
||||
|
||||
// Загружаем подзадачи из драфта
|
||||
draftSubtaskRows, err := a.DB.Query(`
|
||||
SELECT subtask_id
|
||||
FROM task_draft_subtasks
|
||||
WHERE task_draft_id = (SELECT id FROM task_drafts WHERE task_id = $1 AND user_id = $2)
|
||||
`, taskID, userID)
|
||||
if err == nil {
|
||||
defer draftSubtaskRows.Close()
|
||||
draftSubtasks := make([]DraftSubtask, 0)
|
||||
validSubtaskIDs := make(map[int]bool)
|
||||
// Создаем map валидных подзадач для фильтрации
|
||||
for _, subtask := range subtasks {
|
||||
validSubtaskIDs[subtask.Task.ID] = true
|
||||
}
|
||||
|
||||
for draftSubtaskRows.Next() {
|
||||
var subtaskID int
|
||||
if err := draftSubtaskRows.Scan(&subtaskID); err == nil {
|
||||
// Игнорируем подзадачи, которых больше нет в основной задаче
|
||||
if validSubtaskIDs[subtaskID] {
|
||||
draftSubtasks = append(draftSubtasks, DraftSubtask{
|
||||
SubtaskID: subtaskID,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(draftSubtasks) > 0 {
|
||||
response.DraftSubtasks = draftSubtasks
|
||||
}
|
||||
} else if err != sql.ErrNoRows {
|
||||
log.Printf("Error loading draft subtasks for task %d: %v", taskID, err)
|
||||
}
|
||||
} else if err != sql.ErrNoRows {
|
||||
log.Printf("Error loading draft for task %d: %v", taskID, err)
|
||||
}
|
||||
|
||||
// Если задача - тест (есть config_id), загружаем данные конфигурации
|
||||
if configID.Valid {
|
||||
var wordsCount int
|
||||
@@ -7017,6 +7047,7 @@ func (a *App) getTaskDetailHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("Task %d: Sending response with auto_complete = %v (task.AutoComplete = %v)", taskID, response.Task.AutoComplete, task.AutoComplete)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(response)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user