diff --git a/VERSION b/VERSION index 7ea5948..5fb8716 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.8.6 +4.8.7 diff --git a/play-life-backend/main.go b/play-life-backend/main.go index 79f1eac..c862bc8 100644 --- a/play-life-backend/main.go +++ b/play-life-backend/main.go @@ -9400,11 +9400,12 @@ func (a *App) checkWishlistUnlock(itemID int, userID int) (bool, error) { err := a.DB.QueryRow(` SELECT completed FROM tasks - WHERE id = $1 AND user_id = $2 + WHERE id = $1 AND user_id = $2 AND deleted = FALSE `, taskID.Int64, conditionOwnerID).Scan(&completed) if err == sql.ErrNoRows { - conditionMet = false + // Задача удалена или не существует - не блокируем желание + conditionMet = true } else if err != nil { return false, err } else { @@ -9611,7 +9612,7 @@ func (a *App) getWishlistItemsWithConditions(userID int, includeCompleted bool) FROM wishlist_items wi LEFT JOIN wishlist_conditions wc ON wi.id = wc.wishlist_item_id LEFT JOIN task_conditions tc ON wc.task_condition_id = tc.id - LEFT JOIN tasks t ON tc.task_id = t.id + LEFT JOIN tasks t ON tc.task_id = t.id AND t.deleted = FALSE LEFT JOIN score_conditions sc ON wc.score_condition_id = sc.id LEFT JOIN projects p ON sc.project_id = p.id AND p.deleted = FALSE WHERE wi.user_id = $1 @@ -9683,6 +9684,23 @@ func (a *App) getWishlistItemsWithConditions(userID int, includeCompleted bool) // Добавляем условие, если есть if conditionID.Valid { + // Определяем владельца условия + conditionOwnerID := userID + if conditionUserID.Valid { + conditionOwnerID = int(conditionUserID.Int64) + } + + // Если это условие по задаче, проверяем существует ли задача + if taskConditionID.Valid && taskID.Valid { + // Проверяем, существует ли задача (не удалена) + var taskExists bool + err := a.DB.QueryRow(`SELECT EXISTS(SELECT 1 FROM tasks WHERE id = $1 AND user_id = $2 AND deleted = FALSE)`, taskID.Int64, conditionOwnerID).Scan(&taskExists) + if err != nil || !taskExists { + // Задача удалена - не добавляем условие в список, но при проверке блокировки оно считается выполненным + continue + } + } + condition := UnlockConditionDisplay{ ID: int(conditionID.Int64), DisplayOrder: int(displayOrder.Int64), @@ -9760,11 +9778,18 @@ func (a *App) getWishlistItemsWithConditions(userID int, includeCompleted bool) if err == nil { var completed int err = a.DB.QueryRow(` - SELECT completed FROM tasks WHERE id = $1 AND user_id = $2 + SELECT completed FROM tasks WHERE id = $1 AND user_id = $2 AND deleted = FALSE `, taskID, conditionOwnerID).Scan(&completed) - conditionMet = err == nil && completed > 0 - completedBool := conditionMet - condition.TaskCompleted = &completedBool + if err == sql.ErrNoRows { + // Задача удалена или не существует - не блокируем желание + conditionMet = true + completedBool := true + condition.TaskCompleted = &completedBool + } else if err == nil { + conditionMet = completed > 0 + completedBool := conditionMet + condition.TaskCompleted = &completedBool + } } } else if condition.Type == "project_points" { // Находим project_id, required_points и user_id для этого условия @@ -9820,9 +9845,13 @@ func (a *App) getWishlistItemsWithConditions(userID int, includeCompleted bool) if err == nil { var completed int err = a.DB.QueryRow(` - SELECT completed FROM tasks WHERE id = $1 AND user_id = $2 + SELECT completed FROM tasks WHERE id = $1 AND user_id = $2 AND deleted = FALSE `, taskID, conditionOwnerID).Scan(&completed) - if err == nil { + if err == sql.ErrNoRows { + // Задача удалена или не существует - не блокируем желание + completedBool := true + condition.TaskCompleted = &completedBool + } else if err == nil { completedBool := completed > 0 condition.TaskCompleted = &completedBool } @@ -10540,7 +10569,7 @@ func (a *App) getWishlistItemHandler(w http.ResponseWriter, r *http.Request) { FROM wishlist_items wi LEFT JOIN wishlist_conditions wc ON wi.id = wc.wishlist_item_id LEFT JOIN task_conditions tc ON wc.task_condition_id = tc.id - LEFT JOIN tasks t ON tc.task_id = t.id + LEFT JOIN tasks t ON tc.task_id = t.id AND t.deleted = FALSE LEFT JOIN score_conditions sc ON wc.score_condition_id = sc.id LEFT JOIN projects p ON sc.project_id = p.id AND p.deleted = FALSE WHERE wi.id = $1 @@ -10611,16 +10640,31 @@ func (a *App) getWishlistItemHandler(w http.ResponseWriter, r *http.Request) { } if conditionID.Valid { - condition := UnlockConditionDisplay{ - ID: int(conditionID.Int64), - DisplayOrder: int(displayOrder.Int64), - } - // Используем user_id из условия, если он есть, иначе используем владельца желания // Это важно для старых условий, созданных до добавления user_id в wishlist_conditions conditionOwnerID := itemOwnerID if conditionUserID.Valid { conditionOwnerID = int(conditionUserID.Int64) + } + + // Если это условие по задаче, проверяем существует ли задача + if taskConditionID.Valid && taskID.Valid { + // Проверяем, существует ли задача (не удалена) + var taskExists bool + err := a.DB.QueryRow(`SELECT EXISTS(SELECT 1 FROM tasks WHERE id = $1 AND user_id = $2 AND deleted = FALSE)`, taskID.Int64, conditionOwnerID).Scan(&taskExists) + if err != nil || !taskExists { + // Задача удалена - не добавляем условие в список, но при проверке блокировки оно считается выполненным + continue + } + } + + condition := UnlockConditionDisplay{ + ID: int(conditionID.Int64), + DisplayOrder: int(displayOrder.Int64), + } + + if conditionUserID.Valid { + conditionOwnerID := int(conditionUserID.Int64) condition.UserID = &conditionOwnerID } else { condition.UserID = &itemOwnerID @@ -10633,9 +10677,11 @@ func (a *App) getWishlistItemHandler(w http.ResponseWriter, r *http.Request) { } if taskID.Valid { var taskCompleted int - a.DB.QueryRow(`SELECT completed FROM tasks WHERE id = $1 AND user_id = $2`, taskID.Int64, conditionOwnerID).Scan(&taskCompleted) - isCompleted := taskCompleted > 0 - condition.TaskCompleted = &isCompleted + err := a.DB.QueryRow(`SELECT completed FROM tasks WHERE id = $1 AND user_id = $2 AND deleted = FALSE`, taskID.Int64, conditionOwnerID).Scan(&taskCompleted) + if err == nil { + isCompleted := taskCompleted > 0 + condition.TaskCompleted = &isCompleted + } } } else if scoreConditionID.Valid { condition.Type = "project_points" @@ -10893,7 +10939,7 @@ func (a *App) updateWishlistHandler(w http.ResponseWriter, r *http.Request) { FROM wishlist_items wi LEFT JOIN wishlist_conditions wc ON wi.id = wc.wishlist_item_id LEFT JOIN task_conditions tc ON wc.task_condition_id = tc.id - LEFT JOIN tasks t ON tc.task_id = t.id + LEFT JOIN tasks t ON tc.task_id = t.id AND t.deleted = FALSE LEFT JOIN score_conditions sc ON wc.score_condition_id = sc.id LEFT JOIN projects p ON sc.project_id = p.id AND p.deleted = FALSE WHERE wi.id = $1 @@ -10972,14 +11018,30 @@ func (a *App) updateWishlistHandler(w http.ResponseWriter, r *http.Request) { } if conditionID.Valid { + // Определяем владельца условия + conditionOwnerID := itemOwnerID + if conditionUserID.Valid { + conditionOwnerID = int(conditionUserID.Int64) + } + + // Если это условие по задаче, проверяем существует ли задача + if taskConditionID.Valid && taskID.Valid { + // Проверяем, существует ли задача (не удалена) + var taskExists bool + err := a.DB.QueryRow(`SELECT EXISTS(SELECT 1 FROM tasks WHERE id = $1 AND user_id = $2 AND deleted = FALSE)`, taskID.Int64, conditionOwnerID).Scan(&taskExists) + if err != nil || !taskExists { + // Задача удалена - не добавляем условие в список, но при проверке блокировки оно считается выполненным + continue + } + } + condition := UnlockConditionDisplay{ ID: int(conditionID.Int64), DisplayOrder: int(displayOrder.Int64), } - conditionOwnerID := itemOwnerID if conditionUserID.Valid { - conditionOwnerID = int(conditionUserID.Int64) + conditionOwnerID := int(conditionUserID.Int64) condition.UserID = &conditionOwnerID } else { condition.UserID = &itemOwnerID @@ -10992,9 +11054,11 @@ func (a *App) updateWishlistHandler(w http.ResponseWriter, r *http.Request) { } if taskID.Valid { var taskCompleted int - a.DB.QueryRow(`SELECT completed FROM tasks WHERE id = $1 AND user_id = $2`, taskID.Int64, conditionOwnerID).Scan(&taskCompleted) - isCompleted := taskCompleted > 0 - condition.TaskCompleted = &isCompleted + err := a.DB.QueryRow(`SELECT completed FROM tasks WHERE id = $1 AND user_id = $2 AND deleted = FALSE`, taskID.Int64, conditionOwnerID).Scan(&taskCompleted) + if err == nil { + isCompleted := taskCompleted > 0 + condition.TaskCompleted = &isCompleted + } } } else if scoreConditionID.Valid { condition.Type = "project_points" @@ -12625,7 +12689,7 @@ func (a *App) getBoardCompletedHandler(w http.ResponseWriter, r *http.Request) { FROM wishlist_items wi LEFT JOIN wishlist_conditions wc ON wi.id = wc.wishlist_item_id LEFT JOIN task_conditions tc ON wc.task_condition_id = tc.id - LEFT JOIN tasks t ON tc.task_id = t.id + LEFT JOIN tasks t ON tc.task_id = t.id AND t.deleted = FALSE LEFT JOIN score_conditions sc ON wc.score_condition_id = sc.id LEFT JOIN projects p ON sc.project_id = p.id AND p.deleted = FALSE LEFT JOIN users u ON wc.user_id = u.id @@ -12700,6 +12764,23 @@ func (a *App) getBoardCompletedHandler(w http.ResponseWriter, r *http.Request) { } if conditionID.Valid { + // Определяем владельца условия + conditionOwnerID := userID + if userIDCond.Valid { + conditionOwnerID = int(userIDCond.Int64) + } + + // Если это условие по задаче, проверяем существует ли задача + if taskConditionID.Valid && taskID.Valid { + // Проверяем, существует ли задача (не удалена) + var taskExists bool + err := a.DB.QueryRow(`SELECT EXISTS(SELECT 1 FROM tasks WHERE id = $1 AND user_id = $2 AND deleted = FALSE)`, taskID.Int64, conditionOwnerID).Scan(&taskExists) + if err != nil || !taskExists { + // Задача удалена - не добавляем условие в список, но при проверке блокировки оно считается выполненным + continue + } + } + condition := UnlockConditionDisplay{ ID: int(conditionID.Int64), DisplayOrder: int(displayOrder.Int64), @@ -12899,7 +12980,7 @@ func (a *App) getWishlistItemsByBoard(boardID int, userID int) ([]WishlistItem, FROM wishlist_items wi LEFT JOIN wishlist_conditions wc ON wi.id = wc.wishlist_item_id LEFT JOIN task_conditions tc ON wc.task_condition_id = tc.id - LEFT JOIN tasks t ON tc.task_id = t.id + LEFT JOIN tasks t ON tc.task_id = t.id AND t.deleted = FALSE LEFT JOIN score_conditions sc ON wc.score_condition_id = sc.id LEFT JOIN projects p ON sc.project_id = p.id AND p.deleted = FALSE WHERE wi.board_id = $1 @@ -12971,11 +13052,6 @@ func (a *App) getWishlistItemsByBoard(boardID int, userID int) ([]WishlistItem, } if conditionID.Valid { - condition := UnlockConditionDisplay{ - ID: int(conditionID.Int64), - DisplayOrder: int(displayOrder.Int64), - } - // Используем user_id из условия, если он есть, иначе используем владельца желания if !itemOwnerID.Valid { log.Printf("Warning: item_owner_id is NULL for wishlist item %d, skipping condition", itemID) @@ -12984,7 +13060,27 @@ func (a *App) getWishlistItemsByBoard(boardID int, userID int) ([]WishlistItem, conditionOwnerID := int(itemOwnerID.Int64) if conditionUserID.Valid { conditionOwnerID = int(conditionUserID.Int64) - condition.UserID = &conditionOwnerID + } + + // Если это условие по задаче, проверяем существует ли задача + if taskConditionID.Valid && taskID.Valid { + // Проверяем, существует ли задача (не удалена) + var taskExists bool + err := a.DB.QueryRow(`SELECT EXISTS(SELECT 1 FROM tasks WHERE id = $1 AND user_id = $2 AND deleted = FALSE)`, taskID.Int64, conditionOwnerID).Scan(&taskExists) + if err != nil || !taskExists { + // Задача удалена - не добавляем условие в список, но при проверке блокировки оно считается выполненным + continue + } + } + + condition := UnlockConditionDisplay{ + ID: int(conditionID.Int64), + DisplayOrder: int(displayOrder.Int64), + } + + if conditionUserID.Valid { + conditionOwnerIDVal := int(conditionUserID.Int64) + condition.UserID = &conditionOwnerIDVal } else { itemOwnerIDVal := int(itemOwnerID.Int64) condition.UserID = &itemOwnerIDVal @@ -12998,9 +13094,11 @@ func (a *App) getWishlistItemsByBoard(boardID int, userID int) ([]WishlistItem, // Проверяем выполнена ли задача для владельца условия if taskID.Valid { var taskCompleted int - a.DB.QueryRow(`SELECT completed FROM tasks WHERE id = $1 AND user_id = $2`, taskID.Int64, conditionOwnerID).Scan(&taskCompleted) - isCompleted := taskCompleted > 0 - condition.TaskCompleted = &isCompleted + err := a.DB.QueryRow(`SELECT completed FROM tasks WHERE id = $1 AND user_id = $2 AND deleted = FALSE`, taskID.Int64, conditionOwnerID).Scan(&taskCompleted) + if err == nil { + isCompleted := taskCompleted > 0 + condition.TaskCompleted = &isCompleted + } } } else if scoreConditionID.Valid { condition.Type = "project_points" diff --git a/play-life-web/package.json b/play-life-web/package.json index d8a6905..245c8fd 100644 --- a/play-life-web/package.json +++ b/play-life-web/package.json @@ -1,6 +1,6 @@ { "name": "play-life-web", - "version": "4.8.6", + "version": "4.8.7", "type": "module", "scripts": { "dev": "vite",