This commit is contained in:
2026-08-19 02:15:57 +07:00
parent 72605a3cd4
commit 204a20c814
25 changed files with 2892 additions and 500 deletions
+54 -30
View File
@@ -75,17 +75,17 @@ func (r *ScenariosRepo) GetScenariosByAuthorID(
var scenarios []*repos.Scenario
for rows.Next() {
scenario := &repos.Scenario{
Author: &repos.User{},
}
scenario := &repos.Scenario{}
var authorID *int
var authorUsername *string
err := rows.Scan(
&scenario.ID,
&scenario.Name,
&scenario.Description,
&scenario.Image,
&scenario.Scenario,
&scenario.Author.ID,
&scenario.Author.Username,
&authorID,
&authorUsername,
&scenario.Status,
&scenario.UpdatedAt,
&scenario.CreatedAt,
@@ -94,6 +94,9 @@ func (r *ScenariosRepo) GetScenariosByAuthorID(
if err != nil {
return nil, err
}
if authorID != nil && authorUsername != nil {
scenario.Author = &repos.User{ID: *authorID, Username: *authorUsername}
}
scenarios = append(scenarios, scenario)
}
if err := rows.Err(); err != nil {
@@ -134,17 +137,17 @@ func (r *ScenariosRepo) GetScenariosByStatus(
var scenarios []*repos.Scenario
for rows.Next() {
scenario := &repos.Scenario{
Author: &repos.User{},
}
scenario := &repos.Scenario{}
var authorID *int
var authorUsername *string
err := rows.Scan(
&scenario.ID,
&scenario.Name,
&scenario.Description,
&scenario.Image,
&scenario.Scenario,
&scenario.Author.ID,
&scenario.Author.Username,
&authorID,
&authorUsername,
&scenario.Status,
&scenario.UpdatedAt,
&scenario.CreatedAt,
@@ -153,6 +156,9 @@ func (r *ScenariosRepo) GetScenariosByStatus(
if err != nil {
return nil, err
}
if authorID != nil && authorUsername != nil {
scenario.Author = &repos.User{ID: *authorID, Username: *authorUsername}
}
scenarios = append(scenarios, scenario)
}
if err := rows.Err(); err != nil {
@@ -166,9 +172,9 @@ func (r *ScenariosRepo) GetScenarioByID(
ctx context.Context,
id int,
) (*repos.Scenario, error) {
scenario := &repos.Scenario{
Author: &repos.User{},
}
scenario := &repos.Scenario{}
var authorID *int
var authorUsername *string
row := r.pool.QueryRow(
ctx,
`SELECT
@@ -195,8 +201,8 @@ func (r *ScenariosRepo) GetScenarioByID(
&scenario.Description,
&scenario.Image,
&scenario.Scenario,
&scenario.Author.ID,
&scenario.Author.Username,
&authorID,
&authorUsername,
&scenario.Status,
&scenario.UpdatedAt,
&scenario.CreatedAt,
@@ -210,9 +216,15 @@ func (r *ScenariosRepo) GetScenarioByID(
return nil, err
}
// Автор может отсутствовать (обезличен после удаления аккаунта).
if authorID != nil && authorUsername != nil {
scenario.Author = &repos.User{ID: *authorID, Username: *authorUsername}
}
return scenario, nil
}
// UpdateScenarioByID меняет основные поля сценария.
func (r *ScenariosRepo) UpdateScenarioByID(
ctx context.Context,
id int,
@@ -243,50 +255,61 @@ func (r *ScenariosRepo) UpdateScenarioByID(
return nil
}
// UpdateScenarioStatusByID меняет статус сценария. allowPublished=true
// разрешает менять статус опубликованного сценария (только для админа).
// Возвращает false, если строка не обновлена (например, не-админ пытается
// снять с публикации опубликованный сценарий). published_at фиксируется
// только при ПЕРВОЙ публикации: повторная публикация не двигает «момент
// отчуждения» исключительного права (п. 7.2 Пользовательского соглашения).
func (r *ScenariosRepo) UpdateScenarioStatusByID(
ctx context.Context,
id int,
status string,
) error {
allowPublished bool,
) (bool, error) {
tag, err := r.pool.Exec(
ctx,
`UPDATE scenarios
SET
status = $1,
published_at = NOW(),
published_at = CASE
WHEN $1 = 'public' AND published_at IS NULL THEN NOW()
ELSE published_at
END,
updated_at = NOW()
WHERE id = $2`,
WHERE id = $2 AND ($3 OR status <> 'public')`,
status,
id,
allowPublished,
)
if err != nil {
return err
return false, err
}
if tag.RowsAffected() == 0 {
return ErrScenarioNotFound
}
return nil
return tag.RowsAffected() > 0, nil
}
// DeleteScenarioByID помечает сценарий удалённым (soft delete).
// allowPublished=true разрешает удаление опубликованного сценария
// (только для админа). Возвращает false, если строка не обновлена
// (например, не-админ пытается удалить опубликованный сценарий).
func (r *ScenariosRepo) DeleteScenarioByID(
ctx context.Context,
id int,
) error {
allowPublished bool,
) (bool, error) {
tag, err := r.pool.Exec(
ctx,
`UPDATE scenarios
SET
is_deleted = TRUE
WHERE id = $1`,
WHERE id = $1 AND ($2 OR status <> 'public')`,
id,
allowPublished,
)
if err != nil {
return err
return false, err
}
if tag.RowsAffected() == 0 {
return ErrScenarioNotFound
}
return nil
return tag.RowsAffected() > 0, nil
}
func (r *ScenariosRepo) GetStoryByScenarioID(
@@ -315,6 +338,7 @@ func (r *ScenariosRepo) GetStoryByScenarioID(
return story, nil
}
// UpdateStoryByScenarioID обновляет содержимое (историю) сценария.
func (r *ScenariosRepo) UpdateStoryByScenarioID(
ctx context.Context,
id int,