Bump version to 3.4.1 and add version logging on startup
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 44s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 44s
This commit is contained in:
@@ -39,6 +39,8 @@ COPY --from=frontend-builder /app/frontend/dist /usr/share/nginx/html
|
|||||||
# Копируем собранный backend
|
# Копируем собранный backend
|
||||||
COPY --from=backend-builder /app/backend/main /app/backend/main
|
COPY --from=backend-builder /app/backend/main /app/backend/main
|
||||||
COPY play-life-backend/admin.html /app/backend/admin.html
|
COPY play-life-backend/admin.html /app/backend/admin.html
|
||||||
|
# Копируем файл версии
|
||||||
|
COPY VERSION /app/VERSION
|
||||||
|
|
||||||
# Копируем конфигурацию nginx
|
# Копируем конфигурацию nginx
|
||||||
COPY nginx.conf /etc/nginx/nginx.conf
|
COPY nginx.conf /etc/nginx/nginx.conf
|
||||||
|
|||||||
@@ -373,6 +373,48 @@ func calculateNextShowAtFromRepetitionDate(repetitionDate string, fromDate time.
|
|||||||
return &nextDate
|
return &nextDate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// calculateNextShowAtFromRepetitionPeriod calculates the next show date by adding repetition_period to fromDate
|
||||||
|
// Format: PostgreSQL INTERVAL string (e.g., "1 day", "2 weeks", "3 months")
|
||||||
|
func calculateNextShowAtFromRepetitionPeriod(repetitionPeriod string, fromDate time.Time) *time.Time {
|
||||||
|
if repetitionPeriod == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := strings.Fields(strings.TrimSpace(repetitionPeriod))
|
||||||
|
if len(parts) < 2 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
value, err := strconv.Atoi(parts[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
unit := strings.ToLower(parts[1])
|
||||||
|
|
||||||
|
// Start from fromDate at midnight
|
||||||
|
nextDate := time.Date(fromDate.Year(), fromDate.Month(), fromDate.Day(), 0, 0, 0, 0, fromDate.Location())
|
||||||
|
|
||||||
|
switch unit {
|
||||||
|
case "minute", "minutes":
|
||||||
|
nextDate = nextDate.Add(time.Duration(value) * time.Minute)
|
||||||
|
case "hour", "hours":
|
||||||
|
nextDate = nextDate.Add(time.Duration(value) * time.Hour)
|
||||||
|
case "day", "days":
|
||||||
|
nextDate = nextDate.AddDate(0, 0, value)
|
||||||
|
case "week", "weeks":
|
||||||
|
nextDate = nextDate.AddDate(0, 0, value*7)
|
||||||
|
case "month", "months":
|
||||||
|
nextDate = nextDate.AddDate(0, value, 0)
|
||||||
|
case "year", "years":
|
||||||
|
nextDate = nextDate.AddDate(value, 0, 0)
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &nextDate
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// Auth types
|
// Auth types
|
||||||
// ============================================
|
// ============================================
|
||||||
@@ -3524,7 +3566,36 @@ func (a *App) startDailyReportScheduler() {
|
|||||||
// Планировщик будет работать в фоновом режиме
|
// Планировщик будет работать в фоновом режиме
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// readVersion читает версию из файла VERSION
|
||||||
|
func readVersion() string {
|
||||||
|
// Пробуем разные пути к файлу VERSION
|
||||||
|
paths := []string{
|
||||||
|
"/app/VERSION", // В Docker контейнере
|
||||||
|
"../VERSION", // При запуске из play-life-backend/
|
||||||
|
"../../VERSION", // Альтернативный путь
|
||||||
|
"VERSION", // Текущая директория
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, path := range paths {
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
if err == nil {
|
||||||
|
version := strings.TrimSpace(string(data))
|
||||||
|
if version != "" {
|
||||||
|
return version
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
// Читаем версию приложения
|
||||||
|
version := readVersion()
|
||||||
|
log.Printf("========================================")
|
||||||
|
log.Printf("Play Life Backend v%s", version)
|
||||||
|
log.Printf("========================================")
|
||||||
|
|
||||||
// Загружаем переменные окружения из .env файла (если существует)
|
// Загружаем переменные окружения из .env файла (если существует)
|
||||||
// Сначала пробуем загрузить из корня проекта, затем из текущей директории
|
// Сначала пробуем загрузить из корня проекта, затем из текущей директории
|
||||||
// Игнорируем ошибку, если файл не найден
|
// Игнорируем ошибку, если файл не найден
|
||||||
@@ -6805,12 +6876,28 @@ func (a *App) createTaskHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
var insertSQL string
|
var insertSQL string
|
||||||
var insertArgs []interface{}
|
var insertArgs []interface{}
|
||||||
if repetitionPeriod.Valid {
|
if repetitionPeriod.Valid {
|
||||||
insertSQL = `
|
// Вычисляем next_show_at для задачи с repetition_period
|
||||||
INSERT INTO tasks (user_id, name, reward_message, progression_base, repetition_period, repetition_date, completed, deleted)
|
periodStr := strings.TrimSpace(repetitionPeriod.String)
|
||||||
VALUES ($1, $2, $3, $4, $5::INTERVAL, NULL, 0, FALSE)
|
isZeroPeriod := strings.HasPrefix(periodStr, "0 ") || periodStr == "0"
|
||||||
RETURNING id
|
var nextShowAt *time.Time
|
||||||
`
|
if !isZeroPeriod {
|
||||||
insertArgs = []interface{}{userID, strings.TrimSpace(req.Name), rewardMessage, progressionBase, repetitionPeriodValue}
|
nextShowAt = calculateNextShowAtFromRepetitionPeriod(repetitionPeriod.String, time.Now())
|
||||||
|
}
|
||||||
|
if nextShowAt != nil {
|
||||||
|
insertSQL = `
|
||||||
|
INSERT INTO tasks (user_id, name, reward_message, progression_base, repetition_period, repetition_date, next_show_at, completed, deleted)
|
||||||
|
VALUES ($1, $2, $3, $4, $5::INTERVAL, NULL, $6, 0, FALSE)
|
||||||
|
RETURNING id
|
||||||
|
`
|
||||||
|
insertArgs = []interface{}{userID, strings.TrimSpace(req.Name), rewardMessage, progressionBase, repetitionPeriodValue, nextShowAt}
|
||||||
|
} else {
|
||||||
|
insertSQL = `
|
||||||
|
INSERT INTO tasks (user_id, name, reward_message, progression_base, repetition_period, repetition_date, completed, deleted)
|
||||||
|
VALUES ($1, $2, $3, $4, $5::INTERVAL, NULL, 0, FALSE)
|
||||||
|
RETURNING id
|
||||||
|
`
|
||||||
|
insertArgs = []interface{}{userID, strings.TrimSpace(req.Name), rewardMessage, progressionBase, repetitionPeriodValue}
|
||||||
|
}
|
||||||
} else if repetitionDate.Valid {
|
} else if repetitionDate.Valid {
|
||||||
// Вычисляем next_show_at для задачи с repetition_date
|
// Вычисляем next_show_at для задачи с repetition_date
|
||||||
nextShowAt := calculateNextShowAtFromRepetitionDate(repetitionDate.String, time.Now())
|
nextShowAt := calculateNextShowAtFromRepetitionDate(repetitionDate.String, time.Now())
|
||||||
@@ -7062,12 +7149,28 @@ func (a *App) updateTaskHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
var updateSQL string
|
var updateSQL string
|
||||||
var updateArgs []interface{}
|
var updateArgs []interface{}
|
||||||
if repetitionPeriod.Valid {
|
if repetitionPeriod.Valid {
|
||||||
updateSQL = `
|
// Вычисляем next_show_at для задачи с repetition_period
|
||||||
UPDATE tasks
|
periodStr := strings.TrimSpace(repetitionPeriod.String)
|
||||||
SET name = $1, reward_message = $2, progression_base = $3, repetition_period = $4::INTERVAL, repetition_date = NULL, next_show_at = NULL
|
isZeroPeriod := strings.HasPrefix(periodStr, "0 ") || periodStr == "0"
|
||||||
WHERE id = $5
|
var nextShowAt *time.Time
|
||||||
`
|
if !isZeroPeriod {
|
||||||
updateArgs = []interface{}{strings.TrimSpace(req.Name), rewardMessage, progressionBase, repetitionPeriod.String, taskID}
|
nextShowAt = calculateNextShowAtFromRepetitionPeriod(repetitionPeriod.String, time.Now())
|
||||||
|
}
|
||||||
|
if nextShowAt != nil {
|
||||||
|
updateSQL = `
|
||||||
|
UPDATE tasks
|
||||||
|
SET name = $1, reward_message = $2, progression_base = $3, repetition_period = $4::INTERVAL, repetition_date = NULL, next_show_at = $5
|
||||||
|
WHERE id = $6
|
||||||
|
`
|
||||||
|
updateArgs = []interface{}{strings.TrimSpace(req.Name), rewardMessage, progressionBase, repetitionPeriod.String, nextShowAt, taskID}
|
||||||
|
} else {
|
||||||
|
updateSQL = `
|
||||||
|
UPDATE tasks
|
||||||
|
SET name = $1, reward_message = $2, progression_base = $3, repetition_period = $4::INTERVAL, repetition_date = NULL, next_show_at = NULL
|
||||||
|
WHERE id = $5
|
||||||
|
`
|
||||||
|
updateArgs = []interface{}{strings.TrimSpace(req.Name), rewardMessage, progressionBase, repetitionPeriod.String, taskID}
|
||||||
|
}
|
||||||
} else if repetitionDate.Valid {
|
} else if repetitionDate.Valid {
|
||||||
// Вычисляем next_show_at для задачи с repetition_date
|
// Вычисляем next_show_at для задачи с repetition_date
|
||||||
nextShowAt := calculateNextShowAtFromRepetitionDate(repetitionDate.String, time.Now())
|
nextShowAt := calculateNextShowAtFromRepetitionDate(repetitionDate.String, time.Now())
|
||||||
@@ -7706,12 +7809,24 @@ func (a *App) completeTaskHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
`, taskID)
|
`, taskID)
|
||||||
} else {
|
} else {
|
||||||
// Обычный период: обновляем счетчик и last_completed_at, сбрасываем next_show_at
|
// Обычный период: обновляем счетчик и last_completed_at, вычисляем next_show_at
|
||||||
_, err = a.DB.Exec(`
|
// next_show_at = last_completed_at + repetition_period
|
||||||
UPDATE tasks
|
now := time.Now()
|
||||||
SET completed = completed + 1, last_completed_at = NOW(), next_show_at = NULL
|
nextShowAt := calculateNextShowAtFromRepetitionPeriod(repetitionPeriod.String, now)
|
||||||
WHERE id = $1
|
if nextShowAt != nil {
|
||||||
`, taskID)
|
_, err = a.DB.Exec(`
|
||||||
|
UPDATE tasks
|
||||||
|
SET completed = completed + 1, last_completed_at = NOW(), next_show_at = $2
|
||||||
|
WHERE id = $1
|
||||||
|
`, taskID, nextShowAt)
|
||||||
|
} else {
|
||||||
|
// Если не удалось вычислить дату, обновляем как обычно
|
||||||
|
_, err = a.DB.Exec(`
|
||||||
|
UPDATE tasks
|
||||||
|
SET completed = completed + 1, last_completed_at = NOW(), next_show_at = NULL
|
||||||
|
WHERE id = $1
|
||||||
|
`, taskID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_, err = a.DB.Exec(`
|
_, err = a.DB.Exec(`
|
||||||
|
|||||||
Reference in New Issue
Block a user