Rename LMS persona image field to profile_picture.

Add migration 000064 renaming avatar_url column; expose profile_picture in API, sqlc, and Swagger.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Yared Yemane 2026-05-20 06:17:15 -07:00
parent 9631711090
commit 6ab077b53d
10 changed files with 85 additions and 80 deletions

View File

@ -0,0 +1,2 @@
ALTER TABLE lms_personas
RENAME COLUMN profile_picture TO avatar_url;

View File

@ -0,0 +1,3 @@
-- Persona profile image URL stored as profile_picture (replaces avatar_url naming).
ALTER TABLE lms_personas
RENAME COLUMN avatar_url TO profile_picture;

View File

@ -1,5 +1,5 @@
-- name: CreateLmsPersona :one
INSERT INTO lms_personas (name, description, avatar_url, is_active)
INSERT INTO lms_personas (name, description, profile_picture, is_active)
VALUES ($1, $2, $3, $4)
RETURNING *;
@ -13,7 +13,7 @@ UPDATE lms_personas
SET
name = COALESCE(sqlc.narg('name')::varchar, name),
description = COALESCE(sqlc.narg('description')::text, description),
avatar_url = COALESCE(sqlc.narg('avatar_url')::text, avatar_url),
profile_picture = COALESCE(sqlc.narg('profile_picture')::text, profile_picture),
is_active = COALESCE(sqlc.narg('is_active')::boolean, is_active),
updated_at = CURRENT_TIMESTAMP
WHERE id = sqlc.arg('id')
@ -29,7 +29,7 @@ SELECT
p.id,
p.name,
p.description,
p.avatar_url,
p.profile_picture,
p.is_active,
p.created_at,
p.updated_at

View File

@ -10641,9 +10641,6 @@ const docTemplate = `{
"name"
],
"properties": {
"avatar_url": {
"type": "string"
},
"description": {
"type": "string"
},
@ -10652,6 +10649,9 @@ const docTemplate = `{
},
"name": {
"type": "string"
},
"profile_picture": {
"type": "string"
}
}
},
@ -11581,9 +11581,6 @@ const docTemplate = `{
"domain.UpdateLmsPersonaInput": {
"type": "object",
"properties": {
"avatar_url": {
"type": "string"
},
"description": {
"type": "string"
},
@ -11592,6 +11589,9 @@ const docTemplate = `{
},
"name": {
"type": "string"
},
"profile_picture": {
"type": "string"
}
}
},

View File

@ -10633,9 +10633,6 @@
"name"
],
"properties": {
"avatar_url": {
"type": "string"
},
"description": {
"type": "string"
},
@ -10644,6 +10641,9 @@
},
"name": {
"type": "string"
},
"profile_picture": {
"type": "string"
}
}
},
@ -11573,9 +11573,6 @@
"domain.UpdateLmsPersonaInput": {
"type": "object",
"properties": {
"avatar_url": {
"type": "string"
},
"description": {
"type": "string"
},
@ -11584,6 +11581,9 @@
},
"name": {
"type": "string"
},
"profile_picture": {
"type": "string"
}
}
},

View File

@ -449,14 +449,14 @@ definitions:
type: object
domain.CreateLmsPersonaInput:
properties:
avatar_url:
type: string
description:
type: string
is_active:
type: boolean
name:
type: string
profile_picture:
type: string
required:
- name
type: object
@ -1096,14 +1096,14 @@ definitions:
type: object
domain.UpdateLmsPersonaInput:
properties:
avatar_url:
type: string
description:
type: string
is_active:
type: boolean
name:
type: string
profile_picture:
type: string
type: object
domain.UpdateModuleInput:
properties:

View File

@ -12,23 +12,23 @@ import (
)
const CreateLmsPersona = `-- name: CreateLmsPersona :one
INSERT INTO lms_personas (name, description, avatar_url, is_active)
INSERT INTO lms_personas (name, description, profile_picture, is_active)
VALUES ($1, $2, $3, $4)
RETURNING id, name, description, avatar_url, is_active, created_at, updated_at
RETURNING id, name, description, profile_picture, is_active, created_at, updated_at
`
type CreateLmsPersonaParams struct {
Name string `json:"name"`
Description pgtype.Text `json:"description"`
AvatarUrl pgtype.Text `json:"avatar_url"`
IsActive bool `json:"is_active"`
Name string `json:"name"`
Description pgtype.Text `json:"description"`
ProfilePicture pgtype.Text `json:"profile_picture"`
IsActive bool `json:"is_active"`
}
func (q *Queries) CreateLmsPersona(ctx context.Context, arg CreateLmsPersonaParams) (LmsPersona, error) {
row := q.db.QueryRow(ctx, CreateLmsPersona,
arg.Name,
arg.Description,
arg.AvatarUrl,
arg.ProfilePicture,
arg.IsActive,
)
var i LmsPersona
@ -36,7 +36,7 @@ func (q *Queries) CreateLmsPersona(ctx context.Context, arg CreateLmsPersonaPara
&i.ID,
&i.Name,
&i.Description,
&i.AvatarUrl,
&i.ProfilePicture,
&i.IsActive,
&i.CreatedAt,
&i.UpdatedAt,
@ -55,7 +55,7 @@ func (q *Queries) DeleteLmsPersona(ctx context.Context, id int64) error {
}
const GetLmsPersonaByID = `-- name: GetLmsPersonaByID :one
SELECT id, name, description, avatar_url, is_active, created_at, updated_at
SELECT id, name, description, profile_picture, is_active, created_at, updated_at
FROM lms_personas
WHERE id = $1
`
@ -67,7 +67,7 @@ func (q *Queries) GetLmsPersonaByID(ctx context.Context, id int64) (LmsPersona,
&i.ID,
&i.Name,
&i.Description,
&i.AvatarUrl,
&i.ProfilePicture,
&i.IsActive,
&i.CreatedAt,
&i.UpdatedAt,
@ -81,7 +81,7 @@ SELECT
p.id,
p.name,
p.description,
p.avatar_url,
p.profile_picture,
p.is_active,
p.created_at,
p.updated_at
@ -101,14 +101,14 @@ type ListLmsPersonasParams struct {
}
type ListLmsPersonasRow struct {
TotalCount int64 `json:"total_count"`
ID int64 `json:"id"`
Name string `json:"name"`
Description pgtype.Text `json:"description"`
AvatarUrl pgtype.Text `json:"avatar_url"`
IsActive bool `json:"is_active"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
TotalCount int64 `json:"total_count"`
ID int64 `json:"id"`
Name string `json:"name"`
Description pgtype.Text `json:"description"`
ProfilePicture pgtype.Text `json:"profile_picture"`
IsActive bool `json:"is_active"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
func (q *Queries) ListLmsPersonas(ctx context.Context, arg ListLmsPersonasParams) ([]ListLmsPersonasRow, error) {
@ -125,7 +125,7 @@ func (q *Queries) ListLmsPersonas(ctx context.Context, arg ListLmsPersonasParams
&i.ID,
&i.Name,
&i.Description,
&i.AvatarUrl,
&i.ProfilePicture,
&i.IsActive,
&i.CreatedAt,
&i.UpdatedAt,
@ -145,26 +145,26 @@ UPDATE lms_personas
SET
name = COALESCE($1::varchar, name),
description = COALESCE($2::text, description),
avatar_url = COALESCE($3::text, avatar_url),
profile_picture = COALESCE($3::text, profile_picture),
is_active = COALESCE($4::boolean, is_active),
updated_at = CURRENT_TIMESTAMP
WHERE id = $5
RETURNING id, name, description, avatar_url, is_active, created_at, updated_at
RETURNING id, name, description, profile_picture, is_active, created_at, updated_at
`
type UpdateLmsPersonaParams struct {
Name pgtype.Text `json:"name"`
Description pgtype.Text `json:"description"`
AvatarUrl pgtype.Text `json:"avatar_url"`
IsActive pgtype.Bool `json:"is_active"`
ID int64 `json:"id"`
Name pgtype.Text `json:"name"`
Description pgtype.Text `json:"description"`
ProfilePicture pgtype.Text `json:"profile_picture"`
IsActive pgtype.Bool `json:"is_active"`
ID int64 `json:"id"`
}
func (q *Queries) UpdateLmsPersona(ctx context.Context, arg UpdateLmsPersonaParams) (LmsPersona, error) {
row := q.db.QueryRow(ctx, UpdateLmsPersona,
arg.Name,
arg.Description,
arg.AvatarUrl,
arg.ProfilePicture,
arg.IsActive,
arg.ID,
)
@ -173,7 +173,7 @@ func (q *Queries) UpdateLmsPersona(ctx context.Context, arg UpdateLmsPersonaPara
&i.ID,
&i.Name,
&i.Description,
&i.AvatarUrl,
&i.ProfilePicture,
&i.IsActive,
&i.CreatedAt,
&i.UpdatedAt,

View File

@ -139,13 +139,13 @@ type LevelToSubCourse struct {
}
type LmsPersona struct {
ID int64 `json:"id"`
Name string `json:"name"`
Description pgtype.Text `json:"description"`
AvatarUrl pgtype.Text `json:"avatar_url"`
IsActive bool `json:"is_active"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
ID int64 `json:"id"`
Name string `json:"name"`
Description pgtype.Text `json:"description"`
ProfilePicture pgtype.Text `json:"profile_picture"`
IsActive bool `json:"is_active"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type LmsPractice struct {

View File

@ -10,25 +10,25 @@ var ErrPersonaNotFound = errors.New("persona not found")
// LmsPersona is a coach / character profile stored in lms_personas and referenced by practice shells.
type LmsPersona struct {
ID int64 `json:"id"`
Name string `json:"name"`
Description *string `json:"description,omitempty"`
AvatarURL *string `json:"avatar_url,omitempty"`
IsActive bool `json:"is_active"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
ID int64 `json:"id"`
Name string `json:"name"`
Description *string `json:"description,omitempty"`
ProfilePicture *string `json:"profile_picture,omitempty"` // image URL (e.g. MinIO or HTTPS)
IsActive bool `json:"is_active"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
}
type CreateLmsPersonaInput struct {
Name string `json:"name" validate:"required"`
Description *string `json:"description,omitempty"`
AvatarURL *string `json:"avatar_url,omitempty"`
IsActive *bool `json:"is_active,omitempty"`
Name string `json:"name" validate:"required"`
Description *string `json:"description,omitempty"`
ProfilePicture *string `json:"profile_picture,omitempty"`
IsActive *bool `json:"is_active,omitempty"`
}
type UpdateLmsPersonaInput struct {
Name *string `json:"name,omitempty"`
Description *string `json:"description,omitempty"`
AvatarURL *string `json:"avatar_url,omitempty"`
IsActive *bool `json:"is_active,omitempty"`
Name *string `json:"name,omitempty"`
Description *string `json:"description,omitempty"`
ProfilePicture *string `json:"profile_picture,omitempty"`
IsActive *bool `json:"is_active,omitempty"`
}

View File

@ -18,7 +18,7 @@ func lmsPersonaToDomain(p dbgen.LmsPersona) domain.LmsPersona {
IsActive: p.IsActive,
}
out.Description = fromPgText(p.Description)
out.AvatarURL = fromPgText(p.AvatarUrl)
out.ProfilePicture = fromPgText(p.ProfilePicture)
out.CreatedAt = p.CreatedAt.Time
if p.UpdatedAt.Valid {
t := p.UpdatedAt.Time
@ -42,7 +42,7 @@ func (s *Store) CreateLmsPersona(ctx context.Context, in domain.CreateLmsPersona
p, err := s.queries.CreateLmsPersona(ctx, dbgen.CreateLmsPersonaParams{
Name: in.Name,
Description: toPgText(in.Description),
AvatarUrl: toPgText(in.AvatarURL),
ProfilePicture: toPgText(in.ProfilePicture),
IsActive: active,
})
if err != nil {
@ -67,7 +67,7 @@ func (s *Store) UpdateLmsPersona(ctx context.Context, id int64, in domain.Update
ID: id,
Name: optionalTextUpdate(in.Name),
Description: optionalTextUpdate(in.Description),
AvatarUrl: optionalTextUpdate(in.AvatarURL),
ProfilePicture: optionalTextUpdate(in.ProfilePicture),
IsActive: optionalBoolUpdatePB(in.IsActive),
})
if err != nil {
@ -102,13 +102,13 @@ func (s *Store) ListLmsPersonas(ctx context.Context, activeOnly bool, limit, off
total = r.TotalCount
}
out = append(out, lmsPersonaToDomain(dbgen.LmsPersona{
ID: r.ID,
Name: r.Name,
Description: r.Description,
AvatarUrl: r.AvatarUrl,
IsActive: r.IsActive,
CreatedAt: r.CreatedAt,
UpdatedAt: r.UpdatedAt,
ID: r.ID,
Name: r.Name,
Description: r.Description,
ProfilePicture: r.ProfilePicture,
IsActive: r.IsActive,
CreatedAt: r.CreatedAt,
UpdatedAt: r.UpdatedAt,
}))
}
return out, total, nil