Исправление отображения баллов в условиях желаний
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 59s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 59s
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "play-life-web",
|
||||
"version": "3.14.3",
|
||||
"version": "3.14.4",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
Reference in New Issue
Block a user