Files
multica/server/pkg/db/generated/project.sql.go
Jiayuan 2b2e9828ea feat(project): add Project feature with full CRUD and issue association
- Add `project` table with status, color, lead, dates, and sort_order
- Add `project_id` column to `issue` table (nullable FK, ON DELETE SET NULL)
- Implement project CRUD API (POST/GET/PUT/DELETE /api/projects)
- Auto-calculate project progress from issue completion ratio
- Add project_id support to issue create, update, list, and batch operations
- Add WebSocket events (project:created/updated/deleted) with realtime sync
- Add frontend: project types, API client, Zustand store, realtime integration
- Add projects list page (/projects) with create dialog
- Add project detail page (/projects/[id]) with issue list
- Add project picker to issue detail properties sidebar
- Add "Projects" nav item to sidebar
2026-04-05 04:13:07 +08:00

293 lines
7.2 KiB
Go

// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: project.sql
package db
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const createProject = `-- name: CreateProject :one
INSERT INTO project (
workspace_id, name, description, status, icon, color,
lead_type, lead_id, start_date, target_date, sort_order
) VALUES (
$1, $2, $3, $4, $5, $6,
$8, $9,
$10, $11, $7
) RETURNING id, workspace_id, name, description, status, icon, color, lead_type, lead_id, start_date, target_date, sort_order, created_at, updated_at
`
type CreateProjectParams struct {
WorkspaceID pgtype.UUID `json:"workspace_id"`
Name string `json:"name"`
Description pgtype.Text `json:"description"`
Status string `json:"status"`
Icon pgtype.Text `json:"icon"`
Color pgtype.Text `json:"color"`
SortOrder float64 `json:"sort_order"`
LeadType pgtype.Text `json:"lead_type"`
LeadID pgtype.UUID `json:"lead_id"`
StartDate pgtype.Date `json:"start_date"`
TargetDate pgtype.Date `json:"target_date"`
}
func (q *Queries) CreateProject(ctx context.Context, arg CreateProjectParams) (Project, error) {
row := q.db.QueryRow(ctx, createProject,
arg.WorkspaceID,
arg.Name,
arg.Description,
arg.Status,
arg.Icon,
arg.Color,
arg.SortOrder,
arg.LeadType,
arg.LeadID,
arg.StartDate,
arg.TargetDate,
)
var i Project
err := row.Scan(
&i.ID,
&i.WorkspaceID,
&i.Name,
&i.Description,
&i.Status,
&i.Icon,
&i.Color,
&i.LeadType,
&i.LeadID,
&i.StartDate,
&i.TargetDate,
&i.SortOrder,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}
const deleteProject = `-- name: DeleteProject :exec
DELETE FROM project WHERE id = $1 AND workspace_id = $2
`
type DeleteProjectParams struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
}
func (q *Queries) DeleteProject(ctx context.Context, arg DeleteProjectParams) error {
_, err := q.db.Exec(ctx, deleteProject, arg.ID, arg.WorkspaceID)
return err
}
const getProject = `-- name: GetProject :one
SELECT id, workspace_id, name, description, status, icon, color, lead_type, lead_id, start_date, target_date, sort_order, created_at, updated_at FROM project
WHERE id = $1 AND workspace_id = $2
`
type GetProjectParams struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
}
func (q *Queries) GetProject(ctx context.Context, arg GetProjectParams) (Project, error) {
row := q.db.QueryRow(ctx, getProject, arg.ID, arg.WorkspaceID)
var i Project
err := row.Scan(
&i.ID,
&i.WorkspaceID,
&i.Name,
&i.Description,
&i.Status,
&i.Icon,
&i.Color,
&i.LeadType,
&i.LeadID,
&i.StartDate,
&i.TargetDate,
&i.SortOrder,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}
const getProjectProgress = `-- name: GetProjectProgress :one
SELECT
COUNT(*)::int AS total,
COUNT(*) FILTER (WHERE status IN ('done', 'cancelled'))::int AS completed
FROM issue
WHERE project_id = $1 AND workspace_id = $2
`
type GetProjectProgressParams struct {
ProjectID pgtype.UUID `json:"project_id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
}
type GetProjectProgressRow struct {
Total int32 `json:"total"`
Completed int32 `json:"completed"`
}
func (q *Queries) GetProjectProgress(ctx context.Context, arg GetProjectProgressParams) (GetProjectProgressRow, error) {
row := q.db.QueryRow(ctx, getProjectProgress, arg.ProjectID, arg.WorkspaceID)
var i GetProjectProgressRow
err := row.Scan(&i.Total, &i.Completed)
return i, err
}
const listProjects = `-- name: ListProjects :many
SELECT id, workspace_id, name, description, status, icon, color, lead_type, lead_id, start_date, target_date, sort_order, created_at, updated_at FROM project
WHERE workspace_id = $1
AND ($2::text IS NULL OR status = $2)
ORDER BY sort_order ASC, created_at DESC
`
type ListProjectsParams struct {
WorkspaceID pgtype.UUID `json:"workspace_id"`
Status pgtype.Text `json:"status"`
}
func (q *Queries) ListProjects(ctx context.Context, arg ListProjectsParams) ([]Project, error) {
rows, err := q.db.Query(ctx, listProjects, arg.WorkspaceID, arg.Status)
if err != nil {
return nil, err
}
defer rows.Close()
items := []Project{}
for rows.Next() {
var i Project
if err := rows.Scan(
&i.ID,
&i.WorkspaceID,
&i.Name,
&i.Description,
&i.Status,
&i.Icon,
&i.Color,
&i.LeadType,
&i.LeadID,
&i.StartDate,
&i.TargetDate,
&i.SortOrder,
&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 listProjectsProgress = `-- name: ListProjectsProgress :many
SELECT
project_id,
COUNT(*)::int AS total,
COUNT(*) FILTER (WHERE status IN ('done', 'cancelled'))::int AS completed
FROM issue
WHERE workspace_id = $1 AND project_id IS NOT NULL
GROUP BY project_id
`
type ListProjectsProgressRow struct {
ProjectID pgtype.UUID `json:"project_id"`
Total int32 `json:"total"`
Completed int32 `json:"completed"`
}
func (q *Queries) ListProjectsProgress(ctx context.Context, workspaceID pgtype.UUID) ([]ListProjectsProgressRow, error) {
rows, err := q.db.Query(ctx, listProjectsProgress, workspaceID)
if err != nil {
return nil, err
}
defer rows.Close()
items := []ListProjectsProgressRow{}
for rows.Next() {
var i ListProjectsProgressRow
if err := rows.Scan(&i.ProjectID, &i.Total, &i.Completed); 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 project SET
name = COALESCE($3, name),
description = COALESCE($4, description),
status = COALESCE($5, status),
icon = COALESCE($6, icon),
color = COALESCE($7, color),
lead_type = $8,
lead_id = $9,
start_date = $10,
target_date = $11,
sort_order = COALESCE($12, sort_order),
updated_at = now()
WHERE id = $1 AND workspace_id = $2
RETURNING id, workspace_id, name, description, status, icon, color, lead_type, lead_id, start_date, target_date, sort_order, created_at, updated_at
`
type UpdateProjectParams struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
Name pgtype.Text `json:"name"`
Description pgtype.Text `json:"description"`
Status pgtype.Text `json:"status"`
Icon pgtype.Text `json:"icon"`
Color pgtype.Text `json:"color"`
LeadType pgtype.Text `json:"lead_type"`
LeadID pgtype.UUID `json:"lead_id"`
StartDate pgtype.Date `json:"start_date"`
TargetDate pgtype.Date `json:"target_date"`
SortOrder pgtype.Float8 `json:"sort_order"`
}
func (q *Queries) UpdateProject(ctx context.Context, arg UpdateProjectParams) (Project, error) {
row := q.db.QueryRow(ctx, updateProject,
arg.ID,
arg.WorkspaceID,
arg.Name,
arg.Description,
arg.Status,
arg.Icon,
arg.Color,
arg.LeadType,
arg.LeadID,
arg.StartDate,
arg.TargetDate,
arg.SortOrder,
)
var i Project
err := row.Scan(
&i.ID,
&i.WorkspaceID,
&i.Name,
&i.Description,
&i.Status,
&i.Icon,
&i.Color,
&i.LeadType,
&i.LeadID,
&i.StartDate,
&i.TargetDate,
&i.SortOrder,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}