Исправление отображения баллов в условиях желаний
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 59s

This commit is contained in:
poignatov
2026-01-14 18:30:43 +03:00
parent 7200cdfda9
commit c654a01116
3 changed files with 252 additions and 30 deletions

View File

@@ -9244,6 +9244,7 @@ func (a *App) checkWishlistUnlock(itemID int, userID int) (bool, error) {
wc.display_order,
wc.task_condition_id,
wc.score_condition_id,
wc.user_id AS condition_user_id,
tc.task_id,
sc.project_id,
sc.required_points,
@@ -9268,6 +9269,7 @@ func (a *App) checkWishlistUnlock(itemID int, userID int) (bool, error) {
var wcID, displayOrder int
var taskConditionID, scoreConditionID sql.NullInt64
var conditionUserID sql.NullInt64
var taskID sql.NullInt64
var projectID sql.NullInt64
var requiredPoints sql.NullFloat64
@@ -9275,13 +9277,19 @@ func (a *App) checkWishlistUnlock(itemID int, userID int) (bool, error) {
err := rows.Scan(
&wcID, &displayOrder,
&taskConditionID, &scoreConditionID,
&taskConditionID, &scoreConditionID, &conditionUserID,
&taskID, &projectID, &requiredPoints, &startDate,
)
if err != nil {
return false, err
}
// Используем user_id из условия, если он есть, иначе используем текущего пользователя
conditionOwnerID := userID
if conditionUserID.Valid {
conditionOwnerID = int(conditionUserID.Int64)
}
var conditionMet bool
if taskConditionID.Valid {
@@ -9295,7 +9303,7 @@ func (a *App) checkWishlistUnlock(itemID int, userID int) (bool, error) {
SELECT completed
FROM tasks
WHERE id = $1 AND user_id = $2
`, taskID.Int64, userID).Scan(&completed)
`, taskID.Int64, conditionOwnerID).Scan(&completed)
if err == sql.ErrNoRows {
conditionMet = false
@@ -9314,7 +9322,7 @@ func (a *App) checkWishlistUnlock(itemID int, userID int) (bool, error) {
totalScore, err := a.calculateProjectPointsFromDate(
int(projectID.Int64),
startDate,
userID,
conditionOwnerID,
)
if err != nil {
return false, err
@@ -9352,6 +9360,7 @@ func (a *App) getWishlistItemsWithConditions(userID int, includeCompleted bool)
wc.display_order,
wc.task_condition_id,
wc.score_condition_id,
wc.user_id AS condition_user_id,
tc.task_id,
t.name AS task_name,
sc.project_id,
@@ -9388,6 +9397,7 @@ func (a *App) getWishlistItemsWithConditions(userID int, includeCompleted bool)
var conditionID, displayOrder sql.NullInt64
var taskConditionID, scoreConditionID sql.NullInt64
var conditionUserID sql.NullInt64
var taskID sql.NullInt64
var taskName sql.NullString
var projectID sql.NullInt64
@@ -9398,7 +9408,7 @@ func (a *App) getWishlistItemsWithConditions(userID int, includeCompleted bool)
err := rows.Scan(
&itemID, &name, &price, &imagePath, &link, &completed,
&conditionID, &displayOrder,
&taskConditionID, &scoreConditionID,
&taskConditionID, &scoreConditionID, &conditionUserID,
&taskID, &taskName,
&projectID, &projectName, &requiredPoints, &startDate,
)
@@ -9482,36 +9492,38 @@ func (a *App) getWishlistItemsWithConditions(userID int, includeCompleted bool)
var err error
if condition.Type == "task_completion" {
// Находим task_id для этого условия
// Находим task_id и user_id для этого условия
var taskID int
var conditionOwnerID int
err = a.DB.QueryRow(`
SELECT tc.task_id
SELECT tc.task_id, COALESCE(wc.user_id, $2)
FROM wishlist_conditions wc
JOIN task_conditions tc ON wc.task_condition_id = tc.id
WHERE wc.id = $1
`, condition.ID).Scan(&taskID)
`, condition.ID, userID).Scan(&taskID, &conditionOwnerID)
if err == nil {
var completed int
err = a.DB.QueryRow(`
SELECT completed FROM tasks WHERE id = $1 AND user_id = $2
`, taskID, userID).Scan(&completed)
`, taskID, conditionOwnerID).Scan(&completed)
conditionMet = err == nil && completed > 0
completedBool := conditionMet
condition.TaskCompleted = &completedBool
}
} else if condition.Type == "project_points" {
// Находим project_id и required_points для этого условия
// Находим project_id, required_points и user_id для этого условия
var projectID int
var requiredPoints float64
var startDate sql.NullTime
var conditionOwnerID int
err = a.DB.QueryRow(`
SELECT sc.project_id, sc.required_points, sc.start_date
SELECT sc.project_id, sc.required_points, sc.start_date, COALESCE(wc.user_id, $2)
FROM wishlist_conditions wc
JOIN score_conditions sc ON wc.score_condition_id = sc.id
WHERE wc.id = $1
`, condition.ID).Scan(&projectID, &requiredPoints, &startDate)
`, condition.ID, userID).Scan(&projectID, &requiredPoints, &startDate, &conditionOwnerID)
if err == nil {
totalScore, err := a.calculateProjectPointsFromDate(projectID, startDate, userID)
totalScore, err := a.calculateProjectPointsFromDate(projectID, startDate, conditionOwnerID)
if err != nil {
// Если ошибка при расчете, устанавливаем 0
zeroScore := 0.0
@@ -9541,17 +9553,18 @@ func (a *App) getWishlistItemsWithConditions(userID int, includeCompleted bool)
condition := &item.UnlockConditions[i]
if condition.Type == "task_completion" {
var taskID int
var conditionOwnerID int
err := a.DB.QueryRow(`
SELECT tc.task_id
SELECT tc.task_id, COALESCE(wc.user_id, $2)
FROM wishlist_conditions wc
JOIN task_conditions tc ON wc.task_condition_id = tc.id
WHERE wc.id = $1
`, condition.ID).Scan(&taskID)
`, condition.ID, userID).Scan(&taskID, &conditionOwnerID)
if err == nil {
var completed int
err = a.DB.QueryRow(`
SELECT completed FROM tasks WHERE id = $1 AND user_id = $2
`, taskID, userID).Scan(&completed)
`, taskID, conditionOwnerID).Scan(&completed)
if err == nil {
completedBool := completed > 0
condition.TaskCompleted = &completedBool
@@ -9561,14 +9574,15 @@ func (a *App) getWishlistItemsWithConditions(userID int, includeCompleted bool)
var projectID int
var requiredPoints float64
var startDate sql.NullTime
var conditionOwnerID int
err := a.DB.QueryRow(`
SELECT sc.project_id, sc.required_points, sc.start_date
SELECT sc.project_id, sc.required_points, sc.start_date, COALESCE(wc.user_id, $2)
FROM wishlist_conditions wc
JOIN score_conditions sc ON wc.score_condition_id = sc.id
WHERE wc.id = $1
`, condition.ID).Scan(&projectID, &requiredPoints, &startDate)
`, condition.ID, userID).Scan(&projectID, &requiredPoints, &startDate, &conditionOwnerID)
if err == nil {
totalScore, err := a.calculateProjectPointsFromDate(projectID, startDate, userID)
totalScore, err := a.calculateProjectPointsFromDate(projectID, startDate, conditionOwnerID)
if err != nil {
// Если ошибка при расчете, устанавливаем 0
zeroScore := 0.0
@@ -9984,17 +9998,193 @@ func (a *App) getWishlistItemHandler(w http.ResponseWriter, r *http.Request) {
return
}
items, err := a.getWishlistItemsWithConditions(userID, true)
// Проверяем доступ к желанию
var itemUserID int
var boardID sql.NullInt64
err = a.DB.QueryRow(`
SELECT user_id, board_id
FROM wishlist_items
WHERE id = $1 AND deleted = FALSE
`, itemID).Scan(&itemUserID, &boardID)
if err == sql.ErrNoRows {
sendErrorWithCORS(w, "Wishlist item not found", http.StatusNotFound)
return
}
if err != nil {
log.Printf("Error getting wishlist item: %v", err)
sendErrorWithCORS(w, fmt.Sprintf("Error getting wishlist item: %v", err), http.StatusInternalServerError)
sendErrorWithCORS(w, "Error getting wishlist item", http.StatusInternalServerError)
return
}
// Проверяем доступ: владелец ИЛИ участник доски
hasAccess := itemUserID == userID
if !hasAccess && boardID.Valid {
var ownerID int
err = a.DB.QueryRow(`SELECT owner_id FROM wishlist_boards WHERE id = $1 AND deleted = FALSE`, boardID.Int64).Scan(&ownerID)
if err == nil {
hasAccess = ownerID == userID
if !hasAccess {
var isMember bool
a.DB.QueryRow(`SELECT EXISTS(SELECT 1 FROM wishlist_board_members WHERE board_id = $1 AND user_id = $2)`,
int(boardID.Int64), userID).Scan(&isMember)
hasAccess = isMember
}
}
}
if !hasAccess {
sendErrorWithCORS(w, "Access denied", http.StatusForbidden)
return
}
// Сохраняем itemUserID для использования в качестве fallback, если conditionUserID NULL
itemOwnerID := itemUserID
// Загружаем полную информацию о желании
query := `
SELECT
wi.id,
wi.name,
wi.price,
wi.image_path,
wi.link,
wi.completed,
wc.id AS condition_id,
wc.display_order,
wc.task_condition_id,
wc.score_condition_id,
wc.user_id AS condition_user_id,
tc.task_id,
t.name AS task_name,
sc.project_id,
p.name AS project_name,
sc.required_points,
sc.start_date
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 score_conditions sc ON wc.score_condition_id = sc.id
LEFT JOIN projects p ON sc.project_id = p.id
WHERE wi.id = $1
AND wi.deleted = FALSE
ORDER BY wc.display_order, wc.id
`
rows, err := a.DB.Query(query, itemID)
if err != nil {
log.Printf("Error querying wishlist item: %v", err)
sendErrorWithCORS(w, "Error getting wishlist item", http.StatusInternalServerError)
return
}
defer rows.Close()
itemsMap := make(map[int]*WishlistItem)
for rows.Next() {
var itemID int
var name string
var price sql.NullFloat64
var imagePath sql.NullString
var link sql.NullString
var completed bool
var conditionID sql.NullInt64
var displayOrder sql.NullInt64
var taskConditionID sql.NullInt64
var scoreConditionID sql.NullInt64
var conditionUserID sql.NullInt64
var taskID sql.NullInt64
var taskName sql.NullString
var projectID sql.NullInt64
var projectName sql.NullString
var requiredPoints sql.NullFloat64
var startDate sql.NullTime
err := rows.Scan(
&itemID, &name, &price, &imagePath, &link, &completed,
&conditionID, &displayOrder, &taskConditionID, &scoreConditionID, &conditionUserID,
&taskID, &taskName, &projectID, &projectName, &requiredPoints, &startDate,
)
if err != nil {
log.Printf("Error scanning wishlist item: %v", err)
continue
}
item, exists := itemsMap[itemID]
if !exists {
item = &WishlistItem{
ID: itemID,
Name: name,
Completed: completed,
UnlockConditions: []UnlockConditionDisplay{},
}
if price.Valid {
item.Price = &price.Float64
}
if imagePath.Valid && imagePath.String != "" {
url := imagePath.String
if !strings.HasPrefix(url, "http") {
url = url + "?t=" + strconv.FormatInt(time.Now().Unix(), 10)
}
item.ImageURL = &url
}
if link.Valid {
item.Link = &link.String
}
itemsMap[itemID] = item
}
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 {
condition.Type = "task_completion"
if taskName.Valid {
condition.TaskName = &taskName.String
}
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
}
} else if scoreConditionID.Valid {
condition.Type = "project_points"
if projectName.Valid {
condition.ProjectName = &projectName.String
}
if requiredPoints.Valid {
condition.RequiredPoints = &requiredPoints.Float64
}
if startDate.Valid {
dateStr := startDate.Time.Format("2006-01-02")
condition.StartDate = &dateStr
}
if projectID.Valid {
points, _ := a.calculateProjectPointsFromDate(int(projectID.Int64), startDate, conditionOwnerID)
condition.CurrentPoints = &points
}
}
item.UnlockConditions = append(item.UnlockConditions, condition)
}
}
// Получаем желание из map
var item *WishlistItem
for i := range items {
if items[i].ID == itemID {
item = &items[i]
for _, it := range itemsMap {
if it.ID == itemID {
item = it
break
}
}
@@ -10004,6 +10194,30 @@ func (a *App) getWishlistItemHandler(w http.ResponseWriter, r *http.Request) {
return
}
// Проверяем разблокировку
item.Unlocked = true
if len(item.UnlockConditions) > 0 {
for _, cond := range item.UnlockConditions {
if cond.Type == "task_completion" {
if cond.TaskCompleted == nil || !*cond.TaskCompleted {
item.Unlocked = false
break
}
} else if cond.Type == "project_points" {
if cond.CurrentPoints == nil || cond.RequiredPoints == nil || *cond.CurrentPoints < *cond.RequiredPoints {
item.Unlocked = false
break
}
}
}
}
// Также проверяем через checkWishlistUnlock для совместимости
unlocked, err := a.checkWishlistUnlock(itemID, userID)
if err == nil {
item.Unlocked = unlocked
}
// Загружаем связанную задачу, если есть
var linkedTaskID, linkedTaskCompleted, linkedTaskUserID sql.NullInt64
var linkedTaskName sql.NullString
@@ -11772,6 +11986,7 @@ func (a *App) getWishlistItemsByBoard(boardID int, userID int) ([]WishlistItem,
wc.display_order,
wc.task_condition_id,
wc.score_condition_id,
wc.user_id AS condition_user_id,
tc.task_id,
t.name AS task_name,
sc.project_id,
@@ -11809,6 +12024,7 @@ func (a *App) getWishlistItemsByBoard(boardID int, userID int) ([]WishlistItem,
var displayOrder sql.NullInt64
var taskConditionID sql.NullInt64
var scoreConditionID sql.NullInt64
var conditionUserID sql.NullInt64
var taskID sql.NullInt64
var taskName sql.NullString
var projectID sql.NullInt64
@@ -11818,7 +12034,7 @@ func (a *App) getWishlistItemsByBoard(boardID int, userID int) ([]WishlistItem,
err := rows.Scan(
&itemID, &name, &price, &imagePath, &link, &completed,
&conditionID, &displayOrder, &taskConditionID, &scoreConditionID,
&conditionID, &displayOrder, &taskConditionID, &scoreConditionID, &conditionUserID,
&taskID, &taskName, &projectID, &projectName, &requiredPoints, &startDate,
)
if err != nil {
@@ -11856,15 +12072,21 @@ func (a *App) getWishlistItemsByBoard(boardID int, userID int) ([]WishlistItem,
DisplayOrder: int(displayOrder.Int64),
}
// Используем user_id из условия, если он есть, иначе используем текущего пользователя
conditionOwnerID := userID
if conditionUserID.Valid {
conditionOwnerID = int(conditionUserID.Int64)
}
if taskConditionID.Valid {
condition.Type = "task_completion"
if taskName.Valid {
condition.TaskName = &taskName.String
}
// Проверяем выполнена ли задача
// Проверяем выполнена ли задача для владельца условия
if taskID.Valid {
var taskCompleted int
a.DB.QueryRow(`SELECT completed FROM tasks WHERE id = $1`, taskID.Int64).Scan(&taskCompleted)
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
}
@@ -11880,9 +12102,9 @@ func (a *App) getWishlistItemsByBoard(boardID int, userID int) ([]WishlistItem,
dateStr := startDate.Time.Format("2006-01-02")
condition.StartDate = &dateStr
}
// Считаем текущие баллы
// Считаем текущие баллы для владельца условия
if projectID.Valid {
points, _ := a.calculateProjectPointsFromDate(int(projectID.Int64), startDate, userID)
points, _ := a.calculateProjectPointsFromDate(int(projectID.Int64), startDate, conditionOwnerID)
condition.CurrentPoints = &points
}
}