UPDATE: Project Module
All checks were successful
Build and Release / release (push) Successful in 1m15s

This commit is contained in:
2026-04-25 14:05:15 +07:00
parent 44a63f29c6
commit ac90236022
71 changed files with 5110 additions and 257 deletions

View File

@@ -53,6 +53,38 @@ func (q *Queries) DeleteEntity(ctx context.Context, id pgtype.UUID) error {
return err
}
const getEntitiesByIDs = `-- name: GetEntitiesByIDs :many
SELECT id, name, description, thumbnail_url, is_deleted, created_at, updated_at FROM entities WHERE id = ANY($1::uuid[]) AND is_deleted = false
`
func (q *Queries) GetEntitiesByIDs(ctx context.Context, dollar_1 []pgtype.UUID) ([]Entity, error) {
rows, err := q.db.Query(ctx, getEntitiesByIDs, dollar_1)
if err != nil {
return nil, err
}
defer rows.Close()
items := []Entity{}
for rows.Next() {
var i Entity
if err := rows.Scan(
&i.ID,
&i.Name,
&i.Description,
&i.ThumbnailUrl,
&i.IsDeleted,
&i.CreatedAt,
&i.UpdatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getEntityById = `-- name: GetEntityById :one
SELECT id, name, description, thumbnail_url, is_deleted, created_at, updated_at
FROM entities

View File

@@ -132,6 +132,41 @@ func (q *Queries) GetMediaByID(ctx context.Context, id pgtype.UUID) (Media, erro
return i, err
}
const getMediaByIDs = `-- name: GetMediaByIDs :many
SELECT id, user_id, storage_key, original_name, mime_type, size, file_metadata, created_at, updated_at FROM medias
WHERE id = ANY($1::uuid[])
`
func (q *Queries) GetMediaByIDs(ctx context.Context, dollar_1 []pgtype.UUID) ([]Media, error) {
rows, err := q.db.Query(ctx, getMediaByIDs, dollar_1)
if err != nil {
return nil, err
}
defer rows.Close()
items := []Media{}
for rows.Next() {
var i Media
if err := rows.Scan(
&i.ID,
&i.UserID,
&i.StorageKey,
&i.OriginalName,
&i.MimeType,
&i.Size,
&i.FileMetadata,
&i.CreatedAt,
&i.UpdatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getMediasByUserID = `-- name: GetMediasByUserID :many
SELECT id, user_id, storage_key, original_name, mime_type, size, file_metadata, created_at, updated_at FROM medias
WHERE user_id = $1

View File

@@ -67,7 +67,7 @@ RETURNING id, geo_type, draw_geometry, binding, time_start, time_end,
`
type CreateGeometryParams struct {
GeoType string `json:"geo_type"`
GeoType int16 `json:"geo_type"`
DrawGeometry json.RawMessage `json:"draw_geometry"`
Binding []byte `json:"binding"`
TimeStart pgtype.Int4 `json:"time_start"`
@@ -80,7 +80,7 @@ type CreateGeometryParams struct {
type CreateGeometryRow struct {
ID pgtype.UUID `json:"id"`
GeoType string `json:"geo_type"`
GeoType int16 `json:"geo_type"`
DrawGeometry json.RawMessage `json:"draw_geometry"`
Binding []byte `json:"binding"`
TimeStart pgtype.Int4 `json:"time_start"`
@@ -137,6 +137,68 @@ func (q *Queries) DeleteGeometry(ctx context.Context, id pgtype.UUID) error {
return err
}
const getGeometriesByIDs = `-- name: GetGeometriesByIDs :many
SELECT
id, geo_type, draw_geometry, binding, time_start, time_end,
ST_XMin(bbox)::float8 as min_lng,
ST_YMin(bbox)::float8 as min_lat,
ST_XMax(bbox)::float8 as max_lng,
ST_YMax(bbox)::float8 as max_lat,
is_deleted, created_at, updated_at
FROM geometries
WHERE id = ANY($1::uuid[]) AND is_deleted = false
`
type GetGeometriesByIDsRow struct {
ID pgtype.UUID `json:"id"`
GeoType int16 `json:"geo_type"`
DrawGeometry json.RawMessage `json:"draw_geometry"`
Binding []byte `json:"binding"`
TimeStart pgtype.Int4 `json:"time_start"`
TimeEnd pgtype.Int4 `json:"time_end"`
MinLng float64 `json:"min_lng"`
MinLat float64 `json:"min_lat"`
MaxLng float64 `json:"max_lng"`
MaxLat float64 `json:"max_lat"`
IsDeleted bool `json:"is_deleted"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
func (q *Queries) GetGeometriesByIDs(ctx context.Context, dollar_1 []pgtype.UUID) ([]GetGeometriesByIDsRow, error) {
rows, err := q.db.Query(ctx, getGeometriesByIDs, dollar_1)
if err != nil {
return nil, err
}
defer rows.Close()
items := []GetGeometriesByIDsRow{}
for rows.Next() {
var i GetGeometriesByIDsRow
if err := rows.Scan(
&i.ID,
&i.GeoType,
&i.DrawGeometry,
&i.Binding,
&i.TimeStart,
&i.TimeEnd,
&i.MinLng,
&i.MinLat,
&i.MaxLng,
&i.MaxLat,
&i.IsDeleted,
&i.CreatedAt,
&i.UpdatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getGeometryById = `-- name: GetGeometryById :one
SELECT id, geo_type, draw_geometry, binding, time_start, time_end,
ST_XMin(bbox)::float8 as min_lng, ST_YMin(bbox)::float8 as min_lat, ST_XMax(bbox)::float8 as max_lng, ST_YMax(bbox)::float8 as max_lat,
@@ -147,7 +209,7 @@ WHERE id = $1 AND is_deleted = false
type GetGeometryByIdRow struct {
ID pgtype.UUID `json:"id"`
GeoType string `json:"geo_type"`
GeoType int16 `json:"geo_type"`
DrawGeometry json.RawMessage `json:"draw_geometry"`
Binding []byte `json:"binding"`
TimeStart pgtype.Int4 `json:"time_start"`
@@ -232,7 +294,7 @@ type SearchGeometriesParams struct {
type SearchGeometriesRow struct {
ID pgtype.UUID `json:"id"`
GeoType string `json:"geo_type"`
GeoType int16 `json:"geo_type"`
DrawGeometry json.RawMessage `json:"draw_geometry"`
Binding []byte `json:"binding"`
TimeStart pgtype.Int4 `json:"time_start"`
@@ -308,7 +370,7 @@ RETURNING id, geo_type, draw_geometry, binding, time_start, time_end,
`
type UpdateGeometryParams struct {
GeoType pgtype.Text `json:"geo_type"`
GeoType pgtype.Int2 `json:"geo_type"`
DrawGeometry []byte `json:"draw_geometry"`
Binding []byte `json:"binding"`
TimeStart pgtype.Int4 `json:"time_start"`
@@ -323,7 +385,7 @@ type UpdateGeometryParams struct {
type UpdateGeometryRow struct {
ID pgtype.UUID `json:"id"`
GeoType string `json:"geo_type"`
GeoType int16 `json:"geo_type"`
DrawGeometry json.RawMessage `json:"draw_geometry"`
Binding []byte `json:"binding"`
TimeStart pgtype.Int4 `json:"time_start"`

View File

@@ -32,7 +32,7 @@ type EntityWiki struct {
type Geometry struct {
ID pgtype.UUID `json:"id"`
GeoType string `json:"geo_type"`
GeoType int16 `json:"geo_type"`
DrawGeometry json.RawMessage `json:"draw_geometry"`
Binding []byte `json:"binding"`
TimeStart pgtype.Int4 `json:"time_start"`
@@ -55,6 +55,33 @@ type Media struct {
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type Project struct {
ID pgtype.UUID `json:"id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
LatestRevisionID pgtype.UUID `json:"latest_revision_id"`
VersionCount int32 `json:"version_count"`
ProjectStatus int16 `json:"project_status"`
LockedBy pgtype.UUID `json:"locked_by"`
IsDeleted bool `json:"is_deleted"`
UserID pgtype.UUID `json:"user_id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type Revision struct {
ID pgtype.UUID `json:"id"`
ProjectID pgtype.UUID `json:"project_id"`
VersionNo int32 `json:"version_no"`
SnapshotJson json.RawMessage `json:"snapshot_json"`
SnapshotHash pgtype.Text `json:"snapshot_hash"`
ParentID pgtype.UUID `json:"parent_id"`
UserID pgtype.UUID `json:"user_id"`
EditSummary pgtype.Text `json:"edit_summary"`
IsDeleted bool `json:"is_deleted"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type Role struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
@@ -63,6 +90,19 @@ type Role struct {
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type Submission struct {
ID pgtype.UUID `json:"id"`
ProjectID pgtype.UUID `json:"project_id"`
RevisionID pgtype.UUID `json:"revision_id"`
SubmittedBy pgtype.UUID `json:"submitted_by"`
SubmittedAt pgtype.Timestamptz `json:"submitted_at"`
Status int16 `json:"status"`
ReviewedBy pgtype.UUID `json:"reviewed_by"`
ReviewedAt pgtype.Timestamptz `json:"reviewed_at"`
ReviewNote pgtype.Text `json:"review_note"`
IsDeleted bool `json:"is_deleted"`
}
type User struct {
ID pgtype.UUID `json:"id"`
Email string `json:"email"`

View File

@@ -0,0 +1,556 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: project.sql
package sqlc
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const countProjects = `-- name: CountProjects :one
SELECT count(*)
FROM projects p
WHERE p.is_deleted = false
AND (
$1::text[] IS NULL
OR p.project_status = ANY($1::text[])
)
AND ($2::uuid[] IS NULL OR p.user_id = ANY($2::uuid[]))
AND (
$3::text IS NULL OR
p.title ILIKE '%' || $3::text || '%' OR
p.description ILIKE '%' || $3::text || '%'
)
AND ($4::timestamptz IS NULL OR p.created_at >= $4::timestamptz)
AND ($5::timestamptz IS NULL OR p.created_at <= $5::timestamptz)
`
type CountProjectsParams struct {
Statuses []string `json:"statuses"`
UserIds []pgtype.UUID `json:"user_ids"`
SearchText pgtype.Text `json:"search_text"`
CreatedFrom pgtype.Timestamptz `json:"created_from"`
CreatedTo pgtype.Timestamptz `json:"created_to"`
}
func (q *Queries) CountProjects(ctx context.Context, arg CountProjectsParams) (int64, error) {
row := q.db.QueryRow(ctx, countProjects,
arg.Statuses,
arg.UserIds,
arg.SearchText,
arg.CreatedFrom,
arg.CreatedTo,
)
var count int64
err := row.Scan(&count)
return count, err
}
const createProject = `-- name: CreateProject :one
INSERT INTO projects (
title, description, project_status, user_id
) VALUES (
$1, $2, $3, $4
)
RETURNING
id, title, description, latest_revision_id, version_count, project_status, locked_by, is_deleted, user_id, created_at, updated_at,
json_build_object(
'id', u.id,
'email', u.email,
'display_name', up.display_name,
'full_name', up.full_name,
'avatar_url', up.avatar_url
)::json AS user,
'{}'::uuid[] AS commit_ids,
'{}'::uuid[] AS submission_ids
`
type CreateProjectParams struct {
Title string `json:"title"`
Description pgtype.Text `json:"description"`
ProjectStatus int16 `json:"project_status"`
UserID pgtype.UUID `json:"user_id"`
}
type CreateProjectRow struct {
ID pgtype.UUID `json:"id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
LatestRevisionID pgtype.UUID `json:"latest_revision_id"`
VersionCount int32 `json:"version_count"`
ProjectStatus int16 `json:"project_status"`
LockedBy pgtype.UUID `json:"locked_by"`
IsDeleted bool `json:"is_deleted"`
UserID pgtype.UUID `json:"user_id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
User []byte `json:"user"`
CommitIds []pgtype.UUID `json:"commit_ids"`
SubmissionIds []pgtype.UUID `json:"submission_ids"`
}
func (q *Queries) CreateProject(ctx context.Context, arg CreateProjectParams) (CreateProjectRow, error) {
row := q.db.QueryRow(ctx, createProject,
arg.Title,
arg.Description,
arg.ProjectStatus,
arg.UserID,
)
var i CreateProjectRow
err := row.Scan(
&i.ID,
&i.Title,
&i.Description,
&i.LatestRevisionID,
&i.VersionCount,
&i.ProjectStatus,
&i.LockedBy,
&i.IsDeleted,
&i.UserID,
&i.CreatedAt,
&i.UpdatedAt,
&i.User,
&i.CommitIds,
&i.SubmissionIds,
)
return i, err
}
const deleteProject = `-- name: DeleteProject :exec
UPDATE projects
SET
is_deleted = true
WHERE id = $1
`
func (q *Queries) DeleteProject(ctx context.Context, id pgtype.UUID) error {
_, err := q.db.Exec(ctx, deleteProject, id)
return err
}
const getProjectById = `-- name: GetProjectById :one
SELECT
p.id, p.title, p.description, p.latest_revision_id, p.version_count, p.project_status, p.locked_by, p.is_deleted, p.user_id, p.created_at, p.updated_at,
COALESCE(
(SELECT array_agg(id) FROM revisions WHERE project_id = p.id),
'{}'
)::uuid[] AS commit_ids,
COALESCE(
(SELECT array_agg(id) FROM submissions WHERE project_id = p.id),
'{}'
)::uuid[] AS submission_ids,
json_build_object(
'id', u.id,
'email', u.email,
'display_name', up.display_name,
'full_name', up.full_name,
'avatar_url', up.avatar_url
)::json AS user
FROM projects p
JOIN users u ON p.user_id = u.id
LEFT JOIN user_profiles up ON u.id = up.user_id
WHERE p.id = $1 AND p.is_deleted = false
`
type GetProjectByIdRow struct {
ID pgtype.UUID `json:"id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
LatestRevisionID pgtype.UUID `json:"latest_revision_id"`
VersionCount int32 `json:"version_count"`
ProjectStatus int16 `json:"project_status"`
LockedBy pgtype.UUID `json:"locked_by"`
IsDeleted bool `json:"is_deleted"`
UserID pgtype.UUID `json:"user_id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
CommitIds []pgtype.UUID `json:"commit_ids"`
SubmissionIds []pgtype.UUID `json:"submission_ids"`
User []byte `json:"user"`
}
func (q *Queries) GetProjectById(ctx context.Context, id pgtype.UUID) (GetProjectByIdRow, error) {
row := q.db.QueryRow(ctx, getProjectById, id)
var i GetProjectByIdRow
err := row.Scan(
&i.ID,
&i.Title,
&i.Description,
&i.LatestRevisionID,
&i.VersionCount,
&i.ProjectStatus,
&i.LockedBy,
&i.IsDeleted,
&i.UserID,
&i.CreatedAt,
&i.UpdatedAt,
&i.CommitIds,
&i.SubmissionIds,
&i.User,
)
return i, err
}
const getProjectsByIDs = `-- name: GetProjectsByIDs :many
SELECT
p.id, p.title, p.description, p.latest_revision_id, p.version_count, p.project_status, p.locked_by, p.is_deleted, p.user_id, p.created_at, p.updated_at,
COALESCE((SELECT array_agg(id) FROM revisions WHERE project_id = p.id), '{}')::uuid[] AS commit_ids,
COALESCE((SELECT array_agg(id) FROM submissions WHERE project_id = p.id), '{}')::uuid[] AS submission_ids,
json_build_object(
'id', u.id,
'email', u.email,
'display_name', up.display_name,
'full_name', up.full_name,
'avatar_url', up.avatar_url
)::json AS user
FROM projects p
JOIN users u ON p.user_id = u.id
LEFT JOIN user_profiles up ON u.id = up.user_id
WHERE p.id = ANY($1::uuid[]) AND p.is_deleted = false
`
type GetProjectsByIDsRow struct {
ID pgtype.UUID `json:"id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
LatestRevisionID pgtype.UUID `json:"latest_revision_id"`
VersionCount int32 `json:"version_count"`
ProjectStatus int16 `json:"project_status"`
LockedBy pgtype.UUID `json:"locked_by"`
IsDeleted bool `json:"is_deleted"`
UserID pgtype.UUID `json:"user_id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
CommitIds []pgtype.UUID `json:"commit_ids"`
SubmissionIds []pgtype.UUID `json:"submission_ids"`
User []byte `json:"user"`
}
func (q *Queries) GetProjectsByIDs(ctx context.Context, dollar_1 []pgtype.UUID) ([]GetProjectsByIDsRow, error) {
rows, err := q.db.Query(ctx, getProjectsByIDs, dollar_1)
if err != nil {
return nil, err
}
defer rows.Close()
items := []GetProjectsByIDsRow{}
for rows.Next() {
var i GetProjectsByIDsRow
if err := rows.Scan(
&i.ID,
&i.Title,
&i.Description,
&i.LatestRevisionID,
&i.VersionCount,
&i.ProjectStatus,
&i.LockedBy,
&i.IsDeleted,
&i.UserID,
&i.CreatedAt,
&i.UpdatedAt,
&i.CommitIds,
&i.SubmissionIds,
&i.User,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getProjectsByUserId = `-- name: GetProjectsByUserId :many
SELECT
p.id, p.title, p.description, p.latest_revision_id, p.version_count, p.project_status, p.locked_by, p.is_deleted, p.user_id, p.created_at, p.updated_at,
COALESCE(
(SELECT array_agg(id) FROM revisions WHERE project_id = p.id),
'{}'
)::uuid[] AS commit_ids,
COALESCE(
(SELECT array_agg(id) FROM submissions WHERE project_id = p.id),
'{}'
)::uuid[] AS submission_ids,
json_build_object(
'id', u.id,
'email', u.email,
'display_name', up.display_name,
'full_name', up.full_name,
'avatar_url', up.avatar_url
)::json AS user
FROM projects p
JOIN users u ON p.user_id = u.id
LEFT JOIN user_profiles up ON u.id = up.user_id
WHERE p.user_id = $1
AND p.is_deleted = false
AND ($2::uuid IS NULL OR p.id < $2::uuid)
ORDER BY p.updated_at DESC
LIMIT $3
`
type GetProjectsByUserIdParams struct {
UserID pgtype.UUID `json:"user_id"`
CursorID pgtype.UUID `json:"cursor_id"`
Limit int32 `json:"limit"`
}
type GetProjectsByUserIdRow struct {
ID pgtype.UUID `json:"id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
LatestRevisionID pgtype.UUID `json:"latest_revision_id"`
VersionCount int32 `json:"version_count"`
ProjectStatus int16 `json:"project_status"`
LockedBy pgtype.UUID `json:"locked_by"`
IsDeleted bool `json:"is_deleted"`
UserID pgtype.UUID `json:"user_id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
CommitIds []pgtype.UUID `json:"commit_ids"`
SubmissionIds []pgtype.UUID `json:"submission_ids"`
User []byte `json:"user"`
}
func (q *Queries) GetProjectsByUserId(ctx context.Context, arg GetProjectsByUserIdParams) ([]GetProjectsByUserIdRow, error) {
rows, err := q.db.Query(ctx, getProjectsByUserId, arg.UserID, arg.CursorID, arg.Limit)
if err != nil {
return nil, err
}
defer rows.Close()
items := []GetProjectsByUserIdRow{}
for rows.Next() {
var i GetProjectsByUserIdRow
if err := rows.Scan(
&i.ID,
&i.Title,
&i.Description,
&i.LatestRevisionID,
&i.VersionCount,
&i.ProjectStatus,
&i.LockedBy,
&i.IsDeleted,
&i.UserID,
&i.CreatedAt,
&i.UpdatedAt,
&i.CommitIds,
&i.SubmissionIds,
&i.User,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const searchProjects = `-- name: SearchProjects :many
SELECT
p.id, p.title, p.description, p.latest_revision_id, p.version_count, p.project_status, p.locked_by, p.is_deleted, p.user_id, p.created_at, p.updated_at,
COALESCE(
(SELECT array_agg(id) FROM revisions WHERE project_id = p.id),
'{}'
)::uuid[] AS commit_ids,
COALESCE(
(SELECT array_agg(id) FROM submissions WHERE project_id = p.id),
'{}'
)::uuid[] AS submission_ids,
json_build_object(
'id', u.id,
'email', u.email,
'display_name', up.display_name,
'full_name', up.full_name,
'avatar_url', up.avatar_url
)::json AS user
FROM projects p
JOIN users u ON p.user_id = u.id
LEFT JOIN user_profiles up ON u.id = up.user_id
WHERE p.is_deleted = false
AND (
$1::text[] IS NULL
OR p.project_status = ANY($1::text[])
)
AND ($2::uuid[] IS NULL OR p.user_id = ANY($2::uuid[]))
AND (
$3::text IS NULL OR
p.title ILIKE '%' || $3::text || '%' OR
p.description ILIKE '%' || $3::text || '%'
)
AND ($4::timestamptz IS NULL OR p.created_at >= $4::timestamptz)
AND ($5::timestamptz IS NULL OR p.created_at <= $5::timestamptz)
ORDER BY
CASE WHEN $6 = 'created_at' AND $7 = 'asc' THEN p.created_at END ASC,
CASE WHEN $6 = 'created_at' AND $7 = 'desc' THEN p.created_at END DESC,
CASE WHEN $6 = 'updated_at' AND $7 = 'asc' THEN p.updated_at END ASC,
CASE WHEN $6 = 'updated_at' AND $7 = 'desc' THEN p.updated_at END DESC,
CASE WHEN $6 = 'title' AND $7 = 'asc' THEN p.title END ASC,
CASE WHEN $6 = 'title' AND $7 = 'desc' THEN p.title END DESC,
CASE WHEN $6 IS NULL THEN p.updated_at END DESC
LIMIT $9
OFFSET $8
`
type SearchProjectsParams struct {
Statuses []string `json:"statuses"`
UserIds []pgtype.UUID `json:"user_ids"`
SearchText pgtype.Text `json:"search_text"`
CreatedFrom pgtype.Timestamptz `json:"created_from"`
CreatedTo pgtype.Timestamptz `json:"created_to"`
Sort interface{} `json:"sort"`
Order interface{} `json:"order"`
Offset int32 `json:"offset"`
Limit int32 `json:"limit"`
}
type SearchProjectsRow struct {
ID pgtype.UUID `json:"id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
LatestRevisionID pgtype.UUID `json:"latest_revision_id"`
VersionCount int32 `json:"version_count"`
ProjectStatus int16 `json:"project_status"`
LockedBy pgtype.UUID `json:"locked_by"`
IsDeleted bool `json:"is_deleted"`
UserID pgtype.UUID `json:"user_id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
CommitIds []pgtype.UUID `json:"commit_ids"`
SubmissionIds []pgtype.UUID `json:"submission_ids"`
User []byte `json:"user"`
}
func (q *Queries) SearchProjects(ctx context.Context, arg SearchProjectsParams) ([]SearchProjectsRow, error) {
rows, err := q.db.Query(ctx, searchProjects,
arg.Statuses,
arg.UserIds,
arg.SearchText,
arg.CreatedFrom,
arg.CreatedTo,
arg.Sort,
arg.Order,
arg.Offset,
arg.Limit,
)
if err != nil {
return nil, err
}
defer rows.Close()
items := []SearchProjectsRow{}
for rows.Next() {
var i SearchProjectsRow
if err := rows.Scan(
&i.ID,
&i.Title,
&i.Description,
&i.LatestRevisionID,
&i.VersionCount,
&i.ProjectStatus,
&i.LockedBy,
&i.IsDeleted,
&i.UserID,
&i.CreatedAt,
&i.UpdatedAt,
&i.CommitIds,
&i.SubmissionIds,
&i.User,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const updateProject = `-- name: UpdateProject :one
UPDATE projects
SET
title = COALESCE($1, title),
description = COALESCE($2, description),
latest_revision_id = COALESCE($3, latest_revision_id),
version_count = COALESCE($4, version_count),
project_status = COALESCE($5, status),
locked_by = COALESCE($6, locked_by),
updated_at = NOW()
FROM projects p
JOIN users u ON p.user_id = u.id
LEFT JOIN user_profiles up ON u.id = up.user_id
WHERE p.id = $7 AND p.is_deleted = false
RETURNING
p.id, p.title, p.description, p.latest_revision_id, p.version_count, p.project_status, p.locked_by, p.is_deleted, p.user_id, p.created_at, p.updated_at,
json_build_object(
'id', u.id,
'email', u.email,
'display_name', up.display_name,
'full_name', up.full_name,
'avatar_url', up.avatar_url
)::json AS user,
COALESCE((SELECT array_agg(id) FROM revisions WHERE project_id = projects.id), '{}')::uuid[] AS commit_ids,
COALESCE((SELECT array_agg(id) FROM submissions WHERE project_id = projects.id), '{}')::uuid[] AS submission_ids
`
type UpdateProjectParams struct {
Title pgtype.Text `json:"title"`
Description pgtype.Text `json:"description"`
LatestRevisionID pgtype.UUID `json:"latest_revision_id"`
VersionCount pgtype.Int4 `json:"version_count"`
Status pgtype.Int2 `json:"status"`
LockedBy pgtype.UUID `json:"locked_by"`
ID pgtype.UUID `json:"id"`
}
type UpdateProjectRow struct {
ID pgtype.UUID `json:"id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
LatestRevisionID pgtype.UUID `json:"latest_revision_id"`
VersionCount int32 `json:"version_count"`
ProjectStatus int16 `json:"project_status"`
LockedBy pgtype.UUID `json:"locked_by"`
IsDeleted bool `json:"is_deleted"`
UserID pgtype.UUID `json:"user_id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
User []byte `json:"user"`
CommitIds []pgtype.UUID `json:"commit_ids"`
SubmissionIds []pgtype.UUID `json:"submission_ids"`
}
func (q *Queries) UpdateProject(ctx context.Context, arg UpdateProjectParams) (UpdateProjectRow, error) {
row := q.db.QueryRow(ctx, updateProject,
arg.Title,
arg.Description,
arg.LatestRevisionID,
arg.VersionCount,
arg.Status,
arg.LockedBy,
arg.ID,
)
var i UpdateProjectRow
err := row.Scan(
&i.ID,
&i.Title,
&i.Description,
&i.LatestRevisionID,
&i.VersionCount,
&i.ProjectStatus,
&i.LockedBy,
&i.IsDeleted,
&i.UserID,
&i.CreatedAt,
&i.UpdatedAt,
&i.User,
&i.CommitIds,
&i.SubmissionIds,
)
return i, err
}

View File

@@ -0,0 +1,182 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: revision.sql
package sqlc
import (
"context"
"encoding/json"
"github.com/jackc/pgx/v5/pgtype"
)
const createRevision = `-- name: CreateRevision :one
INSERT INTO revisions (
project_id, version_no, snapshot_json, snapshot_hash, parent_id, user_id, edit_summary
) VALUES (
$1, $2, $3, $4, $5, $6, $7
)
RETURNING id, project_id, version_no, snapshot_json, snapshot_hash, parent_id, user_id, edit_summary, is_deleted, created_at
`
type CreateRevisionParams struct {
ProjectID pgtype.UUID `json:"project_id"`
VersionNo int32 `json:"version_no"`
SnapshotJson json.RawMessage `json:"snapshot_json"`
SnapshotHash pgtype.Text `json:"snapshot_hash"`
ParentID pgtype.UUID `json:"parent_id"`
UserID pgtype.UUID `json:"user_id"`
EditSummary pgtype.Text `json:"edit_summary"`
}
func (q *Queries) CreateRevision(ctx context.Context, arg CreateRevisionParams) (Revision, error) {
row := q.db.QueryRow(ctx, createRevision,
arg.ProjectID,
arg.VersionNo,
arg.SnapshotJson,
arg.SnapshotHash,
arg.ParentID,
arg.UserID,
arg.EditSummary,
)
var i Revision
err := row.Scan(
&i.ID,
&i.ProjectID,
&i.VersionNo,
&i.SnapshotJson,
&i.SnapshotHash,
&i.ParentID,
&i.UserID,
&i.EditSummary,
&i.IsDeleted,
&i.CreatedAt,
)
return i, err
}
const deleteRevision = `-- name: DeleteRevision :exec
UPDATE revisions
SET is_deleted = true
WHERE id = $1
`
func (q *Queries) DeleteRevision(ctx context.Context, id pgtype.UUID) error {
_, err := q.db.Exec(ctx, deleteRevision, id)
return err
}
const getRevisionById = `-- name: GetRevisionById :one
SELECT id, project_id, version_no, snapshot_json, snapshot_hash, parent_id, user_id, edit_summary, is_deleted, created_at
FROM revisions
WHERE id = $1 AND is_deleted = false
`
func (q *Queries) GetRevisionById(ctx context.Context, id pgtype.UUID) (Revision, error) {
row := q.db.QueryRow(ctx, getRevisionById, id)
var i Revision
err := row.Scan(
&i.ID,
&i.ProjectID,
&i.VersionNo,
&i.SnapshotJson,
&i.SnapshotHash,
&i.ParentID,
&i.UserID,
&i.EditSummary,
&i.IsDeleted,
&i.CreatedAt,
)
return i, err
}
const getRevisionsByIDs = `-- name: GetRevisionsByIDs :many
SELECT id, project_id, version_no, snapshot_json, snapshot_hash, parent_id, user_id, edit_summary, is_deleted, created_at FROM revisions WHERE id = ANY($1::uuid[]) AND is_deleted = false
`
func (q *Queries) GetRevisionsByIDs(ctx context.Context, dollar_1 []pgtype.UUID) ([]Revision, error) {
rows, err := q.db.Query(ctx, getRevisionsByIDs, dollar_1)
if err != nil {
return nil, err
}
defer rows.Close()
items := []Revision{}
for rows.Next() {
var i Revision
if err := rows.Scan(
&i.ID,
&i.ProjectID,
&i.VersionNo,
&i.SnapshotJson,
&i.SnapshotHash,
&i.ParentID,
&i.UserID,
&i.EditSummary,
&i.IsDeleted,
&i.CreatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const searchRevisions = `-- name: SearchRevisions :many
SELECT id, project_id, version_no, snapshot_json, snapshot_hash, parent_id, user_id, edit_summary, is_deleted, created_at
FROM revisions
WHERE is_deleted = false
AND ($1::uuid IS NULL OR project_id = $1)
AND ($2::uuid IS NULL OR user_id = $2)
AND ($3::uuid IS NULL OR id < $3::uuid)
ORDER BY version_no DESC
LIMIT $4
`
type SearchRevisionsParams struct {
ProjectID pgtype.UUID `json:"project_id"`
UserID pgtype.UUID `json:"user_id"`
CursorID pgtype.UUID `json:"cursor_id"`
Limit int32 `json:"limit"`
}
func (q *Queries) SearchRevisions(ctx context.Context, arg SearchRevisionsParams) ([]Revision, error) {
rows, err := q.db.Query(ctx, searchRevisions,
arg.ProjectID,
arg.UserID,
arg.CursorID,
arg.Limit,
)
if err != nil {
return nil, err
}
defer rows.Close()
items := []Revision{}
for rows.Next() {
var i Revision
if err := rows.Scan(
&i.ID,
&i.ProjectID,
&i.VersionNo,
&i.SnapshotJson,
&i.SnapshotHash,
&i.ParentID,
&i.UserID,
&i.EditSummary,
&i.IsDeleted,
&i.CreatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}

View File

@@ -0,0 +1,493 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: submission.sql
package sqlc
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const countSubmissions = `-- name: CountSubmissions :one
SELECT count(*)
FROM submissions s
WHERE s.is_deleted = false
AND ($1::uuid IS NULL OR s.project_id = $1)
AND ($2::uuid IS NULL OR s.submitted_by = $2)
AND ($3::uuid IS NULL OR s.reviewed_by = $3)
AND (
$4::text[] IS NULL
OR s.status = ANY($4::text[])
)
AND ($5::timestamptz IS NULL OR s.submitted_at >= $5::timestamptz)
AND ($6::timestamptz IS NULL OR s.submitted_at <= $6::timestamptz)
AND (
$7::text IS NULL OR
s.id::text ILIKE '%' || $7::text || '%' OR
s.review_note ILIKE '%' || $7::text || '%'
)
`
type CountSubmissionsParams struct {
ProjectID pgtype.UUID `json:"project_id"`
SubmittedBy pgtype.UUID `json:"submitted_by"`
ReviewedBy pgtype.UUID `json:"reviewed_by"`
Statuses []string `json:"statuses"`
CreatedFrom pgtype.Timestamptz `json:"created_from"`
CreatedTo pgtype.Timestamptz `json:"created_to"`
SearchText pgtype.Text `json:"search_text"`
}
func (q *Queries) CountSubmissions(ctx context.Context, arg CountSubmissionsParams) (int64, error) {
row := q.db.QueryRow(ctx, countSubmissions,
arg.ProjectID,
arg.SubmittedBy,
arg.ReviewedBy,
arg.Statuses,
arg.CreatedFrom,
arg.CreatedTo,
arg.SearchText,
)
var count int64
err := row.Scan(&count)
return count, err
}
const createSubmission = `-- name: CreateSubmission :one
WITH inserted_submission AS (
INSERT INTO submissions (
project_id, revision_id, submitted_by, status
) VALUES (
$1, $2, $3, $4
)
RETURNING id, project_id, revision_id, submitted_by, submitted_at, status, reviewed_by, reviewed_at, review_note, is_deleted
)
SELECT
s.id, s.project_id, s.revision_id, s.submitted_by, s.submitted_at, s.status, s.reviewed_by, s.reviewed_at, s.review_note, s.is_deleted,
json_build_object(
'id', u.id,
'email', u.email,
'display_name', up.display_name,
'full_name', up.full_name,
'avatar_url', up.avatar_url
)::json AS submitter,
CASE WHEN s.reviewed_by IS NOT NULL THEN
json_build_object(
'id', ru.id,
'email', ru.email,
'display_name', rup.display_name,
'full_name', rup.full_name,
'avatar_url', rup.avatar_url
)::json
ELSE NULL::json END AS reviewer
FROM inserted_submission s
JOIN users u ON s.submitted_by = u.id
LEFT JOIN user_profiles up ON u.id = up.user_id
LEFT JOIN users ru ON s.reviewed_by = ru.id
LEFT JOIN user_profiles rup ON ru.id = rup.user_id
`
type CreateSubmissionParams struct {
ProjectID pgtype.UUID `json:"project_id"`
RevisionID pgtype.UUID `json:"revision_id"`
SubmittedBy pgtype.UUID `json:"submitted_by"`
Status int16 `json:"status"`
}
type CreateSubmissionRow struct {
ID pgtype.UUID `json:"id"`
ProjectID pgtype.UUID `json:"project_id"`
RevisionID pgtype.UUID `json:"revision_id"`
SubmittedBy pgtype.UUID `json:"submitted_by"`
SubmittedAt pgtype.Timestamptz `json:"submitted_at"`
Status int16 `json:"status"`
ReviewedBy pgtype.UUID `json:"reviewed_by"`
ReviewedAt pgtype.Timestamptz `json:"reviewed_at"`
ReviewNote pgtype.Text `json:"review_note"`
IsDeleted bool `json:"is_deleted"`
Submitter []byte `json:"submitter"`
Reviewer []byte `json:"reviewer"`
}
func (q *Queries) CreateSubmission(ctx context.Context, arg CreateSubmissionParams) (CreateSubmissionRow, error) {
row := q.db.QueryRow(ctx, createSubmission,
arg.ProjectID,
arg.RevisionID,
arg.SubmittedBy,
arg.Status,
)
var i CreateSubmissionRow
err := row.Scan(
&i.ID,
&i.ProjectID,
&i.RevisionID,
&i.SubmittedBy,
&i.SubmittedAt,
&i.Status,
&i.ReviewedBy,
&i.ReviewedAt,
&i.ReviewNote,
&i.IsDeleted,
&i.Submitter,
&i.Reviewer,
)
return i, err
}
const deleteSubmission = `-- name: DeleteSubmission :exec
UPDATE submissions
SET is_deleted = true
WHERE id = $1
`
func (q *Queries) DeleteSubmission(ctx context.Context, id pgtype.UUID) error {
_, err := q.db.Exec(ctx, deleteSubmission, id)
return err
}
const getSubmissionById = `-- name: GetSubmissionById :one
SELECT
s.id, s.project_id, s.revision_id, s.submitted_by, s.submitted_at, s.status, s.reviewed_by, s.reviewed_at, s.review_note, s.is_deleted,
json_build_object(
'id', u.id,
'email', u.email,
'display_name', up.display_name,
'full_name', up.full_name,
'avatar_url', up.avatar_url
)::json AS submitter,
CASE WHEN s.reviewed_by IS NOT NULL THEN
json_build_object(
'id', ru.id,
'email', ru.email,
'display_name', rup.display_name,
'full_name', rup.full_name,
'avatar_url', rup.avatar_url
)::json
ELSE NULL::json END AS reviewer
FROM submissions s
JOIN users u ON s.submitted_by = u.id
LEFT JOIN user_profiles up ON u.id = up.user_id
LEFT JOIN users ru ON s.reviewed_by = ru.id
LEFT JOIN user_profiles rup ON ru.id = rup.user_id
WHERE s.id = $1 AND s.is_deleted = false
`
type GetSubmissionByIdRow struct {
ID pgtype.UUID `json:"id"`
ProjectID pgtype.UUID `json:"project_id"`
RevisionID pgtype.UUID `json:"revision_id"`
SubmittedBy pgtype.UUID `json:"submitted_by"`
SubmittedAt pgtype.Timestamptz `json:"submitted_at"`
Status int16 `json:"status"`
ReviewedBy pgtype.UUID `json:"reviewed_by"`
ReviewedAt pgtype.Timestamptz `json:"reviewed_at"`
ReviewNote pgtype.Text `json:"review_note"`
IsDeleted bool `json:"is_deleted"`
Submitter []byte `json:"submitter"`
Reviewer []byte `json:"reviewer"`
}
func (q *Queries) GetSubmissionById(ctx context.Context, id pgtype.UUID) (GetSubmissionByIdRow, error) {
row := q.db.QueryRow(ctx, getSubmissionById, id)
var i GetSubmissionByIdRow
err := row.Scan(
&i.ID,
&i.ProjectID,
&i.RevisionID,
&i.SubmittedBy,
&i.SubmittedAt,
&i.Status,
&i.ReviewedBy,
&i.ReviewedAt,
&i.ReviewNote,
&i.IsDeleted,
&i.Submitter,
&i.Reviewer,
)
return i, err
}
const getSubmissionsByIDs = `-- name: GetSubmissionsByIDs :many
SELECT
s.id, s.project_id, s.revision_id, s.submitted_by, s.submitted_at, s.status, s.reviewed_by, s.reviewed_at, s.review_note, s.is_deleted,
json_build_object(
'id', u.id,
'email', u.email,
'display_name', up.display_name,
'full_name', up.full_name,
'avatar_url', up.avatar_url
)::json AS submitter,
CASE WHEN s.reviewed_by IS NOT NULL THEN
json_build_object(
'id', ru.id,
'email', ru.email,
'display_name', rup.display_name,
'full_name', rup.full_name,
'avatar_url', rup.avatar_url
)::json
ELSE NULL::json END AS reviewer
FROM submissions s
JOIN users u ON s.submitted_by = u.id
LEFT JOIN user_profiles up ON u.id = up.user_id
LEFT JOIN users ru ON s.reviewed_by = ru.id
LEFT JOIN user_profiles rup ON ru.id = rup.user_id
WHERE s.id = ANY($1::uuid[]) AND s.is_deleted = false
`
type GetSubmissionsByIDsRow struct {
ID pgtype.UUID `json:"id"`
ProjectID pgtype.UUID `json:"project_id"`
RevisionID pgtype.UUID `json:"revision_id"`
SubmittedBy pgtype.UUID `json:"submitted_by"`
SubmittedAt pgtype.Timestamptz `json:"submitted_at"`
Status int16 `json:"status"`
ReviewedBy pgtype.UUID `json:"reviewed_by"`
ReviewedAt pgtype.Timestamptz `json:"reviewed_at"`
ReviewNote pgtype.Text `json:"review_note"`
IsDeleted bool `json:"is_deleted"`
Submitter []byte `json:"submitter"`
Reviewer []byte `json:"reviewer"`
}
func (q *Queries) GetSubmissionsByIDs(ctx context.Context, dollar_1 []pgtype.UUID) ([]GetSubmissionsByIDsRow, error) {
rows, err := q.db.Query(ctx, getSubmissionsByIDs, dollar_1)
if err != nil {
return nil, err
}
defer rows.Close()
items := []GetSubmissionsByIDsRow{}
for rows.Next() {
var i GetSubmissionsByIDsRow
if err := rows.Scan(
&i.ID,
&i.ProjectID,
&i.RevisionID,
&i.SubmittedBy,
&i.SubmittedAt,
&i.Status,
&i.ReviewedBy,
&i.ReviewedAt,
&i.ReviewNote,
&i.IsDeleted,
&i.Submitter,
&i.Reviewer,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const searchSubmissions = `-- name: SearchSubmissions :many
SELECT
s.id, s.project_id, s.revision_id, s.submitted_by, s.submitted_at, s.status, s.reviewed_by, s.reviewed_at, s.review_note, s.is_deleted,
json_build_object(
'id', u.id,
'email', u.email,
'display_name', up.display_name,
'full_name', up.full_name,
'avatar_url', up.avatar_url
)::json AS submitter,
CASE WHEN s.reviewed_by IS NOT NULL THEN
json_build_object(
'id', ru.id,
'email', ru.email,
'display_name', rup.display_name,
'full_name', rup.full_name,
'avatar_url', rup.avatar_url
)::json
ELSE NULL::json END AS reviewer
FROM submissions s
JOIN users u ON s.submitted_by = u.id
LEFT JOIN user_profiles up ON u.id = up.user_id
LEFT JOIN users ru ON s.reviewed_by = ru.id
LEFT JOIN user_profiles rup ON ru.id = rup.user_id
WHERE s.is_deleted = false
AND ($1::uuid IS NULL OR s.project_id = $1)
AND ($2::uuid IS NULL OR s.submitted_by = $2)
AND ($3::uuid IS NULL OR s.reviewed_by = $3)
AND (
$4::text[] IS NULL
OR s.status = ANY($4::text[])
)
AND ($5::timestamptz IS NULL OR s.submitted_at >= $5::timestamptz)
AND ($6::timestamptz IS NULL OR s.submitted_at <= $6::timestamptz)
AND (
$7::text IS NULL OR
s.id::text ILIKE '%' || $7::text || '%' OR
s.review_note ILIKE '%' || $7::text || '%'
)
ORDER BY
CASE WHEN $8 = 'submitted_at' AND $9 = 'asc' THEN s.submitted_at END ASC,
CASE WHEN $8 = 'submitted_at' AND $9 = 'desc' THEN s.submitted_at END DESC,
CASE WHEN $8 = 'reviewed_at' AND $9 = 'asc' THEN s.reviewed_at END ASC,
CASE WHEN $8 = 'reviewed_at' AND $9 = 'desc' THEN s.reviewed_at END DESC,
CASE WHEN $8 = 'status' AND $9 = 'asc' THEN s.status END ASC,
CASE WHEN $8 = 'status' AND $9 = 'desc' THEN s.status END DESC,
CASE WHEN $8 IS NULL THEN s.submitted_at END DESC
LIMIT $11
OFFSET $10
`
type SearchSubmissionsParams struct {
ProjectID pgtype.UUID `json:"project_id"`
SubmittedBy pgtype.UUID `json:"submitted_by"`
ReviewedBy pgtype.UUID `json:"reviewed_by"`
Statuses []string `json:"statuses"`
CreatedFrom pgtype.Timestamptz `json:"created_from"`
CreatedTo pgtype.Timestamptz `json:"created_to"`
SearchText pgtype.Text `json:"search_text"`
Sort interface{} `json:"sort"`
Order interface{} `json:"order"`
Offset int32 `json:"offset"`
Limit int32 `json:"limit"`
}
type SearchSubmissionsRow struct {
ID pgtype.UUID `json:"id"`
ProjectID pgtype.UUID `json:"project_id"`
RevisionID pgtype.UUID `json:"revision_id"`
SubmittedBy pgtype.UUID `json:"submitted_by"`
SubmittedAt pgtype.Timestamptz `json:"submitted_at"`
Status int16 `json:"status"`
ReviewedBy pgtype.UUID `json:"reviewed_by"`
ReviewedAt pgtype.Timestamptz `json:"reviewed_at"`
ReviewNote pgtype.Text `json:"review_note"`
IsDeleted bool `json:"is_deleted"`
Submitter []byte `json:"submitter"`
Reviewer []byte `json:"reviewer"`
}
func (q *Queries) SearchSubmissions(ctx context.Context, arg SearchSubmissionsParams) ([]SearchSubmissionsRow, error) {
rows, err := q.db.Query(ctx, searchSubmissions,
arg.ProjectID,
arg.SubmittedBy,
arg.ReviewedBy,
arg.Statuses,
arg.CreatedFrom,
arg.CreatedTo,
arg.SearchText,
arg.Sort,
arg.Order,
arg.Offset,
arg.Limit,
)
if err != nil {
return nil, err
}
defer rows.Close()
items := []SearchSubmissionsRow{}
for rows.Next() {
var i SearchSubmissionsRow
if err := rows.Scan(
&i.ID,
&i.ProjectID,
&i.RevisionID,
&i.SubmittedBy,
&i.SubmittedAt,
&i.Status,
&i.ReviewedBy,
&i.ReviewedAt,
&i.ReviewNote,
&i.IsDeleted,
&i.Submitter,
&i.Reviewer,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const updateSubmission = `-- name: UpdateSubmission :one
UPDATE submissions
SET
status = COALESCE($1, status),
reviewed_by = COALESCE($2, reviewed_by),
reviewed_at = COALESCE($3, reviewed_at),
review_note = COALESCE($4, review_note)
FROM submissions s
JOIN users u ON s.submitted_by = u.id
LEFT JOIN user_profiles up ON u.id = up.user_id
LEFT JOIN users ru ON s.reviewed_by = ru.id
LEFT JOIN user_profiles rup ON ru.id = rup.user_id
WHERE s.id = $5
RETURNING
s.id, s.project_id, s.revision_id, s.submitted_by, s.submitted_at, s.status, s.reviewed_by, s.reviewed_at, s.review_note, s.is_deleted,
json_build_object(
'id', u.id,
'email', u.email,
'display_name', up.display_name,
'full_name', up.full_name,
'avatar_url', up.avatar_url
)::json AS submitter,
CASE WHEN s.reviewed_by IS NOT NULL THEN
json_build_object(
'id', ru.id,
'email', ru.email,
'display_name', rup.display_name,
'full_name', rup.full_name,
'avatar_url', rup.avatar_url
)::json
ELSE NULL::json END AS reviewer
`
type UpdateSubmissionParams struct {
Status pgtype.Int2 `json:"status"`
ReviewedBy pgtype.UUID `json:"reviewed_by"`
ReviewedAt pgtype.Timestamptz `json:"reviewed_at"`
ReviewNote pgtype.Text `json:"review_note"`
ID pgtype.UUID `json:"id"`
}
type UpdateSubmissionRow struct {
ID pgtype.UUID `json:"id"`
ProjectID pgtype.UUID `json:"project_id"`
RevisionID pgtype.UUID `json:"revision_id"`
SubmittedBy pgtype.UUID `json:"submitted_by"`
SubmittedAt pgtype.Timestamptz `json:"submitted_at"`
Status int16 `json:"status"`
ReviewedBy pgtype.UUID `json:"reviewed_by"`
ReviewedAt pgtype.Timestamptz `json:"reviewed_at"`
ReviewNote pgtype.Text `json:"review_note"`
IsDeleted bool `json:"is_deleted"`
Submitter []byte `json:"submitter"`
Reviewer []byte `json:"reviewer"`
}
func (q *Queries) UpdateSubmission(ctx context.Context, arg UpdateSubmissionParams) (UpdateSubmissionRow, error) {
row := q.db.QueryRow(ctx, updateSubmission,
arg.Status,
arg.ReviewedBy,
arg.ReviewedAt,
arg.ReviewNote,
arg.ID,
)
var i UpdateSubmissionRow
err := row.Scan(
&i.ID,
&i.ProjectID,
&i.RevisionID,
&i.SubmittedBy,
&i.SubmittedAt,
&i.Status,
&i.ReviewedBy,
&i.ReviewedAt,
&i.ReviewNote,
&i.IsDeleted,
&i.Submitter,
&i.Reviewer,
)
return i, err
}

View File

@@ -341,6 +341,84 @@ func (q *Queries) GetUserByIDWithoutDeleted(ctx context.Context, id pgtype.UUID)
return i, err
}
const getUsersByIDs = `-- name: GetUsersByIDs :many
SELECT
u.id,
u.email,
u.password_hash,
u.token_version,
u.is_deleted,
u.created_at,
u.updated_at,
(
SELECT json_build_object(
'display_name', p.display_name,
'full_name', p.full_name,
'avatar_url', p.avatar_url,
'bio', p.bio,
'location', p.location,
'website', p.website,
'country_code', p.country_code,
'phone', p.phone
)
FROM user_profiles p
WHERE p.user_id = u.id
) AS profile,
(
SELECT COALESCE(
json_agg(json_build_object('id', r.id, 'name', r.name)),
'[]'
)::json
FROM user_roles ur
JOIN roles r ON ur.role_id = r.id
WHERE ur.user_id = u.id
) AS roles
FROM users u
WHERE u.id = ANY($1::uuid[]) AND u.is_deleted = false
`
type GetUsersByIDsRow struct {
ID pgtype.UUID `json:"id"`
Email string `json:"email"`
PasswordHash pgtype.Text `json:"password_hash"`
TokenVersion int32 `json:"token_version"`
IsDeleted bool `json:"is_deleted"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
Profile json.RawMessage `json:"profile"`
Roles []byte `json:"roles"`
}
func (q *Queries) GetUsersByIDs(ctx context.Context, dollar_1 []pgtype.UUID) ([]GetUsersByIDsRow, error) {
rows, err := q.db.Query(ctx, getUsersByIDs, dollar_1)
if err != nil {
return nil, err
}
defer rows.Close()
items := []GetUsersByIDsRow{}
for rows.Next() {
var i GetUsersByIDsRow
if err := rows.Scan(
&i.ID,
&i.Email,
&i.PasswordHash,
&i.TokenVersion,
&i.IsDeleted,
&i.CreatedAt,
&i.UpdatedAt,
&i.Profile,
&i.Roles,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const restoreUser = `-- name: RestoreUser :exec
UPDATE users
SET

View File

@@ -111,7 +111,7 @@ SELECT
'full_name', up.full_name,
'avatar_url', up.avatar_url
)::json AS user,
NULL::json AS reviewer, -- Khi mới tạo thì reviewer luôn null
NULL::json AS reviewer,
'[]'::json AS medias
FROM inserted_uv i
JOIN users u ON i.user_id = u.id
@@ -387,6 +387,101 @@ func (q *Queries) GetUserVerifications(ctx context.Context, userID pgtype.UUID)
return items, nil
}
const getUserVerificationsByIDs = `-- name: GetUserVerificationsByIDs :many
SELECT
uv.id, uv.verify_type, uv.content,
uv.is_deleted, uv.status, uv.review_note,
uv.reviewed_at, uv.created_at,
json_build_object(
'id', u.id,
'email', u.email,
'display_name', up.display_name,
'full_name', up.full_name,
'avatar_url', up.avatar_url
)::json AS user,
CASE WHEN uv.reviewed_by IS NOT NULL THEN
json_build_object(
'id', ru.id,
'email', ru.email,
'display_name', rup.display_name,
'full_name', rup.full_name,
'avatar_url', rup.avatar_url
)::json
ELSE NULL::json END AS reviewer,
(
SELECT COALESCE(
json_agg(
json_build_object(
'id', m.id,
'storage_key', m.storage_key,
'original_name', m.original_name,
'mime_type', m.mime_type,
'size', m.size,
'file_metadata', m.file_metadata,
'created_at', m.created_at
)
),
'[]'
)::json
FROM verification_medias vm
JOIN medias m ON vm.media_id = m.id
WHERE vm.verification_id = uv.id
) AS medias
FROM user_verifications uv
JOIN users u ON uv.user_id = u.id
LEFT JOIN user_profiles up ON u.id = up.user_id
LEFT JOIN users ru ON uv.reviewed_by = ru.id
LEFT JOIN user_profiles rup ON ru.id = rup.user_id
WHERE uv.id = ANY($1::uuid[])
AND uv.is_deleted = false
`
type GetUserVerificationsByIDsRow struct {
ID pgtype.UUID `json:"id"`
VerifyType int16 `json:"verify_type"`
Content pgtype.Text `json:"content"`
IsDeleted bool `json:"is_deleted"`
Status int16 `json:"status"`
ReviewNote pgtype.Text `json:"review_note"`
ReviewedAt pgtype.Timestamptz `json:"reviewed_at"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
User []byte `json:"user"`
Reviewer []byte `json:"reviewer"`
Medias []byte `json:"medias"`
}
func (q *Queries) GetUserVerificationsByIDs(ctx context.Context, dollar_1 []pgtype.UUID) ([]GetUserVerificationsByIDsRow, error) {
rows, err := q.db.Query(ctx, getUserVerificationsByIDs, dollar_1)
if err != nil {
return nil, err
}
defer rows.Close()
items := []GetUserVerificationsByIDsRow{}
for rows.Next() {
var i GetUserVerificationsByIDsRow
if err := rows.Scan(
&i.ID,
&i.VerifyType,
&i.Content,
&i.IsDeleted,
&i.Status,
&i.ReviewNote,
&i.ReviewedAt,
&i.CreatedAt,
&i.User,
&i.Reviewer,
&i.Medias,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const searchUserVerifications = `-- name: SearchUserVerifications :many
SELECT
uv.id,

View File

@@ -114,6 +114,37 @@ func (q *Queries) GetWikiById(ctx context.Context, id pgtype.UUID) (Wiki, error)
return i, err
}
const getWikisByIDs = `-- name: GetWikisByIDs :many
SELECT id, title, content, is_deleted, created_at, updated_at FROM wikis WHERE id = ANY($1::uuid[]) AND is_deleted = false
`
func (q *Queries) GetWikisByIDs(ctx context.Context, dollar_1 []pgtype.UUID) ([]Wiki, error) {
rows, err := q.db.Query(ctx, getWikisByIDs, dollar_1)
if err != nil {
return nil, err
}
defer rows.Close()
items := []Wiki{}
for rows.Next() {
var i Wiki
if err := rows.Scan(
&i.ID,
&i.Title,
&i.Content,
&i.IsDeleted,
&i.CreatedAt,
&i.UpdatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const searchWikis = `-- name: SearchWikis :many
SELECT w.id, w.title, w.content, w.is_deleted, w.created_at, w.updated_at
FROM wikis w