feat(console,api): implement /console Admin Dashboard and Go backend full CRUD REST APIs
- Add comprehensive /console admin web UI for managing research projects, areas, members, publications, patents, lectures, and standards - Implement Admin token authentication middleware (RequireAdminToken) with Bearer token validation - Implement POST, PUT, DELETE REST API endpoints for all database entities across 5 domains - Add typed admin API client in refer_landing_page/lib/adminApi.ts with localStorage session persistence - Enhance E2E test runner to manage backend server lifecycle during automated tests - Pass all 12 quality gates cleanly with unanimous reviewer PASS verdicts
This commit is contained in:
@@ -55,6 +55,54 @@ func (r *HomeRepository) GetResearchProjects(ctx context.Context) ([]models.Rese
|
||||
return projects, nil
|
||||
}
|
||||
|
||||
func (r *HomeRepository) CreateResearchProject(ctx context.Context, p models.ResearchProject) (int, error) {
|
||||
kwBytes, _ := json.Marshal(p.Keywords)
|
||||
if p.Keywords == nil {
|
||||
kwBytes = []byte("[]")
|
||||
}
|
||||
res, err := r.db.ExecContext(ctx, `
|
||||
INSERT INTO research_projects (slug, title, abstract, keywords, organization, standards_org, period, funder)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`, p.Slug, p.Title, p.Abstract, string(kwBytes), p.Organization, p.StandardsOrg, p.Period, p.Funder)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("insert research project: %w", err)
|
||||
}
|
||||
id, err := res.LastInsertId()
|
||||
return int(id), err
|
||||
}
|
||||
|
||||
func (r *HomeRepository) UpdateResearchProject(ctx context.Context, id int, p models.ResearchProject) error {
|
||||
kwBytes, _ := json.Marshal(p.Keywords)
|
||||
if p.Keywords == nil {
|
||||
kwBytes = []byte("[]")
|
||||
}
|
||||
res, err := r.db.ExecContext(ctx, `
|
||||
UPDATE research_projects
|
||||
SET slug = ?, title = ?, abstract = ?, keywords = ?, organization = ?, standards_org = ?, period = ?, funder = ?, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ?
|
||||
`, p.Slug, p.Title, p.Abstract, string(kwBytes), p.Organization, p.StandardsOrg, p.Period, p.Funder, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("update research project: %w", err)
|
||||
}
|
||||
rows, err := res.RowsAffected()
|
||||
if err == nil && rows == 0 {
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *HomeRepository) DeleteResearchProject(ctx context.Context, id int) error {
|
||||
res, err := r.db.ExecContext(ctx, `DELETE FROM research_projects WHERE id = ?`, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("delete research project: %w", err)
|
||||
}
|
||||
rows, err := res.RowsAffected()
|
||||
if err == nil && rows == 0 {
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *HomeRepository) GetResearchAreas(ctx context.Context) ([]models.ResearchArea, error) {
|
||||
query := `
|
||||
SELECT id, name_en, name_kr, display_order
|
||||
@@ -78,6 +126,46 @@ func (r *HomeRepository) GetResearchAreas(ctx context.Context) ([]models.Researc
|
||||
return areas, rows.Err()
|
||||
}
|
||||
|
||||
func (r *HomeRepository) CreateResearchArea(ctx context.Context, a models.ResearchArea) (int, error) {
|
||||
res, err := r.db.ExecContext(ctx, `
|
||||
INSERT INTO research_areas (name_en, name_kr, display_order)
|
||||
VALUES (?, ?, ?)
|
||||
`, a.NameEn, a.NameKr, a.DisplayOrder)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("insert research area: %w", err)
|
||||
}
|
||||
id, err := res.LastInsertId()
|
||||
return int(id), err
|
||||
}
|
||||
|
||||
func (r *HomeRepository) UpdateResearchArea(ctx context.Context, id int, a models.ResearchArea) error {
|
||||
res, err := r.db.ExecContext(ctx, `
|
||||
UPDATE research_areas
|
||||
SET name_en = ?, name_kr = ?, display_order = ?
|
||||
WHERE id = ?
|
||||
`, a.NameEn, a.NameKr, a.DisplayOrder, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("update research area: %w", err)
|
||||
}
|
||||
rows, err := res.RowsAffected()
|
||||
if err == nil && rows == 0 {
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *HomeRepository) DeleteResearchArea(ctx context.Context, id int) error {
|
||||
res, err := r.db.ExecContext(ctx, `DELETE FROM research_areas WHERE id = ?`, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("delete research area: %w", err)
|
||||
}
|
||||
rows, err := res.RowsAffected()
|
||||
if err == nil && rows == 0 {
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *HomeRepository) GetStatsSummary(ctx context.Context) (*models.StatsSummary, error) {
|
||||
var summary models.StatsSummary
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ func NewLecturesRepository(db *sql.DB) *LecturesRepository {
|
||||
}
|
||||
|
||||
func (r *LecturesRepository) GetSemestersWithCourses(ctx context.Context) ([]models.SemesterWithCourses, error) {
|
||||
// Query semesters ordered by year DESC and Fall before Spring within same year
|
||||
semQuery := `
|
||||
SELECT id, year, term
|
||||
FROM semesters
|
||||
@@ -30,7 +29,7 @@ func (r *LecturesRepository) GetSemestersWithCourses(ctx context.Context) ([]mod
|
||||
defer semRows.Close()
|
||||
|
||||
var semesters []models.SemesterWithCourses
|
||||
semMap := make(map[int]int) // semester_id -> index in slice
|
||||
semMap := make(map[int]int)
|
||||
|
||||
for semRows.Next() {
|
||||
var s models.SemesterWithCourses
|
||||
@@ -45,7 +44,6 @@ func (r *LecturesRepository) GetSemestersWithCourses(ctx context.Context) ([]mod
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Query courses ordered by display_order ASC, id ASC
|
||||
courseQuery := `
|
||||
SELECT id, semester_id, code, name_en, name_kr, note, display_order
|
||||
FROM courses
|
||||
@@ -69,3 +67,83 @@ func (r *LecturesRepository) GetSemestersWithCourses(ctx context.Context) ([]mod
|
||||
|
||||
return semesters, courseRows.Err()
|
||||
}
|
||||
|
||||
func (r *LecturesRepository) CreateSemester(ctx context.Context, s models.Semester) (int, error) {
|
||||
res, err := r.db.ExecContext(ctx, `
|
||||
INSERT INTO semesters (year, term)
|
||||
VALUES (?, ?)
|
||||
`, s.Year, s.Term)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("insert semester: %w", err)
|
||||
}
|
||||
id, err := res.LastInsertId()
|
||||
return int(id), err
|
||||
}
|
||||
|
||||
func (r *LecturesRepository) UpdateSemester(ctx context.Context, id int, s models.Semester) error {
|
||||
res, err := r.db.ExecContext(ctx, `
|
||||
UPDATE semesters
|
||||
SET year = ?, term = ?
|
||||
WHERE id = ?
|
||||
`, s.Year, s.Term, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("update semester: %w", err)
|
||||
}
|
||||
rows, err := res.RowsAffected()
|
||||
if err == nil && rows == 0 {
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *LecturesRepository) DeleteSemester(ctx context.Context, id int) error {
|
||||
res, err := r.db.ExecContext(ctx, `DELETE FROM semesters WHERE id = ?`, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("delete semester: %w", err)
|
||||
}
|
||||
rows, err := res.RowsAffected()
|
||||
if err == nil && rows == 0 {
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *LecturesRepository) CreateCourse(ctx context.Context, c models.Course) (int, error) {
|
||||
res, err := r.db.ExecContext(ctx, `
|
||||
INSERT INTO courses (semester_id, code, name_en, name_kr, note, display_order)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
`, c.SemesterID, c.Code, c.NameEn, c.NameKr, c.Note, c.DisplayOrder)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("insert course: %w", err)
|
||||
}
|
||||
id, err := res.LastInsertId()
|
||||
return int(id), err
|
||||
}
|
||||
|
||||
func (r *LecturesRepository) UpdateCourse(ctx context.Context, id int, c models.Course) error {
|
||||
res, err := r.db.ExecContext(ctx, `
|
||||
UPDATE courses
|
||||
SET code = ?, name_en = ?, name_kr = ?, note = ?, display_order = ?
|
||||
WHERE id = ?
|
||||
`, c.Code, c.NameEn, c.NameKr, c.Note, c.DisplayOrder, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("update course: %w", err)
|
||||
}
|
||||
rows, err := res.RowsAffected()
|
||||
if err == nil && rows == 0 {
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *LecturesRepository) DeleteCourse(ctx context.Context, id int) error {
|
||||
res, err := r.db.ExecContext(ctx, `DELETE FROM courses WHERE id = ?`, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("delete course: %w", err)
|
||||
}
|
||||
rows, err := res.RowsAffected()
|
||||
if err == nil && rows == 0 {
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -42,6 +42,46 @@ func (r *MembersRepository) GetMembers(ctx context.Context) ([]models.Member, er
|
||||
return members, rows.Err()
|
||||
}
|
||||
|
||||
func (r *MembersRepository) CreateMember(ctx context.Context, m models.Member) (int, error) {
|
||||
res, err := r.db.ExecContext(ctx, `
|
||||
INSERT INTO members (name_ko, name_en, degree, affiliation, email, is_advisor, display_order)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
`, m.NameKo, m.NameEn, m.Degree, m.Affiliation, m.Email, m.IsAdvisor, m.DisplayOrder)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("insert member: %w", err)
|
||||
}
|
||||
id, err := res.LastInsertId()
|
||||
return int(id), err
|
||||
}
|
||||
|
||||
func (r *MembersRepository) UpdateMember(ctx context.Context, id int, m models.Member) error {
|
||||
res, err := r.db.ExecContext(ctx, `
|
||||
UPDATE members
|
||||
SET name_ko = ?, name_en = ?, degree = ?, affiliation = ?, email = ?, is_advisor = ?, display_order = ?
|
||||
WHERE id = ?
|
||||
`, m.NameKo, m.NameEn, m.Degree, m.Affiliation, m.Email, m.IsAdvisor, m.DisplayOrder, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("update member: %w", err)
|
||||
}
|
||||
rows, err := res.RowsAffected()
|
||||
if err == nil && rows == 0 {
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *MembersRepository) DeleteMember(ctx context.Context, id int) error {
|
||||
res, err := r.db.ExecContext(ctx, `DELETE FROM members WHERE id = ?`, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("delete member: %w", err)
|
||||
}
|
||||
rows, err := res.RowsAffected()
|
||||
if err == nil && rows == 0 {
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *MembersRepository) GetAlumni(ctx context.Context) ([]models.Alumnus, error) {
|
||||
query := `
|
||||
SELECT id, name_ko, name_en, degree, graduated_at, major, current_position, created_at
|
||||
@@ -67,3 +107,43 @@ func (r *MembersRepository) GetAlumni(ctx context.Context) ([]models.Alumnus, er
|
||||
}
|
||||
return alumni, rows.Err()
|
||||
}
|
||||
|
||||
func (r *MembersRepository) CreateAlumnus(ctx context.Context, a models.Alumnus) (int, error) {
|
||||
res, err := r.db.ExecContext(ctx, `
|
||||
INSERT INTO alumni (name_ko, name_en, degree, graduated_at, major, current_position)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
`, a.NameKo, a.NameEn, a.Degree, a.GraduatedAt, a.Major, a.CurrentPosition)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("insert alumnus: %w", err)
|
||||
}
|
||||
id, err := res.LastInsertId()
|
||||
return int(id), err
|
||||
}
|
||||
|
||||
func (r *MembersRepository) UpdateAlumnus(ctx context.Context, id int, a models.Alumnus) error {
|
||||
res, err := r.db.ExecContext(ctx, `
|
||||
UPDATE alumni
|
||||
SET name_ko = ?, name_en = ?, degree = ?, graduated_at = ?, major = ?, current_position = ?
|
||||
WHERE id = ?
|
||||
`, a.NameKo, a.NameEn, a.Degree, a.GraduatedAt, a.Major, a.CurrentPosition, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("update alumnus: %w", err)
|
||||
}
|
||||
rows, err := res.RowsAffected()
|
||||
if err == nil && rows == 0 {
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *MembersRepository) DeleteAlumnus(ctx context.Context, id int) error {
|
||||
res, err := r.db.ExecContext(ctx, `DELETE FROM alumni WHERE id = ?`, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("delete alumnus: %w", err)
|
||||
}
|
||||
rows, err := res.RowsAffected()
|
||||
if err == nil && rows == 0 {
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -48,6 +48,46 @@ func (r *PublicationsRepository) GetPublications(ctx context.Context, category s
|
||||
return pubs, rows.Err()
|
||||
}
|
||||
|
||||
func (r *PublicationsRepository) CreatePublication(ctx context.Context, p models.Publication) (int, error) {
|
||||
res, err := r.db.ExecContext(ctx, `
|
||||
INSERT INTO publications (category, title, authors, venue, volume, published_at, kci, doi, is_highlight)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`, p.Category, p.Title, p.Authors, p.Venue, p.Volume, p.PublishedAt, p.KCI, p.DOI, p.IsHighlight)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("insert publication: %w", err)
|
||||
}
|
||||
id, err := res.LastInsertId()
|
||||
return int(id), err
|
||||
}
|
||||
|
||||
func (r *PublicationsRepository) UpdatePublication(ctx context.Context, id int, p models.Publication) error {
|
||||
res, err := r.db.ExecContext(ctx, `
|
||||
UPDATE publications
|
||||
SET category = ?, title = ?, authors = ?, venue = ?, volume = ?, published_at = ?, kci = ?, doi = ?, is_highlight = ?
|
||||
WHERE id = ?
|
||||
`, p.Category, p.Title, p.Authors, p.Venue, p.Volume, p.PublishedAt, p.KCI, p.DOI, p.IsHighlight, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("update publication: %w", err)
|
||||
}
|
||||
rows, err := res.RowsAffected()
|
||||
if err == nil && rows == 0 {
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *PublicationsRepository) DeletePublication(ctx context.Context, id int) error {
|
||||
res, err := r.db.ExecContext(ctx, `DELETE FROM publications WHERE id = ?`, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("delete publication: %w", err)
|
||||
}
|
||||
rows, err := res.RowsAffected()
|
||||
if err == nil && rows == 0 {
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *PublicationsRepository) GetHighlights(ctx context.Context) ([]models.Publication, error) {
|
||||
query := `
|
||||
SELECT id, category, title, authors, venue, volume, published_at, kci, doi, is_highlight, created_at
|
||||
@@ -100,3 +140,43 @@ func (r *PublicationsRepository) GetPatents(ctx context.Context) ([]models.Paten
|
||||
}
|
||||
return patents, rows.Err()
|
||||
}
|
||||
|
||||
func (r *PublicationsRepository) CreatePatent(ctx context.Context, p models.Patent) (int, error) {
|
||||
res, err := r.db.ExecContext(ctx, `
|
||||
INSERT INTO patents (title, inventors, application_no, application_at, registration_no, registration_at, country, published_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`, p.Title, p.Inventors, p.ApplicationNo, p.ApplicationAt, p.RegistrationNo, p.RegistrationAt, p.Country, p.PublishedAt)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("insert patent: %w", err)
|
||||
}
|
||||
id, err := res.LastInsertId()
|
||||
return int(id), err
|
||||
}
|
||||
|
||||
func (r *PublicationsRepository) UpdatePatent(ctx context.Context, id int, p models.Patent) error {
|
||||
res, err := r.db.ExecContext(ctx, `
|
||||
UPDATE patents
|
||||
SET title = ?, inventors = ?, application_no = ?, application_at = ?, registration_no = ?, registration_at = ?, country = ?, published_at = ?
|
||||
WHERE id = ?
|
||||
`, p.Title, p.Inventors, p.ApplicationNo, p.ApplicationAt, p.RegistrationNo, p.RegistrationAt, p.Country, p.PublishedAt, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("update patent: %w", err)
|
||||
}
|
||||
rows, err := res.RowsAffected()
|
||||
if err == nil && rows == 0 {
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *PublicationsRepository) DeletePatent(ctx context.Context, id int) error {
|
||||
res, err := r.db.ExecContext(ctx, `DELETE FROM patents WHERE id = ?`, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("delete patent: %w", err)
|
||||
}
|
||||
rows, err := res.RowsAffected()
|
||||
if err == nil && rows == 0 {
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ func NewStandardizationRepository(db *sql.DB) *StandardizationRepository {
|
||||
}
|
||||
|
||||
func (r *StandardizationRepository) GetStandardsBodiesWithProjects(ctx context.Context) ([]models.StandardsBodyWithProjects, error) {
|
||||
// Query bodies ordered by display_order
|
||||
bodyQuery := `
|
||||
SELECT id, org, full_name, scope, period, role, display_order
|
||||
FROM standards_bodies
|
||||
@@ -30,7 +29,7 @@ func (r *StandardizationRepository) GetStandardsBodiesWithProjects(ctx context.C
|
||||
defer bodyRows.Close()
|
||||
|
||||
var bodies []models.StandardsBodyWithProjects
|
||||
bodyMap := make(map[int]int) // body_id -> index in bodies
|
||||
bodyMap := make(map[int]int)
|
||||
|
||||
for bodyRows.Next() {
|
||||
var b models.StandardsBodyWithProjects
|
||||
@@ -45,7 +44,6 @@ func (r *StandardizationRepository) GetStandardsBodiesWithProjects(ctx context.C
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Query documents ordered by body_id, and preserves curated insertion order with MIN(id) ASC
|
||||
docQuery := `
|
||||
SELECT id, body_id, wg, project_name, title, doc_ref, status, published_at
|
||||
FROM standard_documents
|
||||
@@ -57,13 +55,12 @@ func (r *StandardizationRepository) GetStandardsBodiesWithProjects(ctx context.C
|
||||
}
|
||||
defer docRows.Close()
|
||||
|
||||
// Group documents into projects under each body preserving curated order
|
||||
type projectKey struct {
|
||||
bodyID int
|
||||
wg string
|
||||
projectName string
|
||||
}
|
||||
projectMap := make(map[projectKey]int) // projectKey -> index in bodies[bIdx].Projects
|
||||
projectMap := make(map[projectKey]int)
|
||||
|
||||
for docRows.Next() {
|
||||
var d models.StandardDocument
|
||||
@@ -93,3 +90,83 @@ func (r *StandardizationRepository) GetStandardsBodiesWithProjects(ctx context.C
|
||||
|
||||
return bodies, docRows.Err()
|
||||
}
|
||||
|
||||
func (r *StandardizationRepository) CreateStandardsBody(ctx context.Context, b models.StandardsBody) (int, error) {
|
||||
res, err := r.db.ExecContext(ctx, `
|
||||
INSERT INTO standards_bodies (org, full_name, scope, period, role, display_order)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
`, b.Org, b.FullName, b.Scope, b.Period, b.Role, b.DisplayOrder)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("insert standards body: %w", err)
|
||||
}
|
||||
id, err := res.LastInsertId()
|
||||
return int(id), err
|
||||
}
|
||||
|
||||
func (r *StandardizationRepository) UpdateStandardsBody(ctx context.Context, id int, b models.StandardsBody) error {
|
||||
res, err := r.db.ExecContext(ctx, `
|
||||
UPDATE standards_bodies
|
||||
SET org = ?, full_name = ?, scope = ?, period = ?, role = ?, display_order = ?
|
||||
WHERE id = ?
|
||||
`, b.Org, b.FullName, b.Scope, b.Period, b.Role, b.DisplayOrder, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("update standards body: %w", err)
|
||||
}
|
||||
rows, err := res.RowsAffected()
|
||||
if err == nil && rows == 0 {
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *StandardizationRepository) DeleteStandardsBody(ctx context.Context, id int) error {
|
||||
res, err := r.db.ExecContext(ctx, `DELETE FROM standards_bodies WHERE id = ?`, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("delete standards body: %w", err)
|
||||
}
|
||||
rows, err := res.RowsAffected()
|
||||
if err == nil && rows == 0 {
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *StandardizationRepository) CreateStandardDocument(ctx context.Context, d models.StandardDocument) (int, error) {
|
||||
res, err := r.db.ExecContext(ctx, `
|
||||
INSERT INTO standard_documents (body_id, wg, project_name, title, doc_ref, status, published_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
`, d.BodyID, d.WG, d.ProjectName, d.Title, d.DocRef, d.Status, d.PublishedAt)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("insert standard document: %w", err)
|
||||
}
|
||||
id, err := res.LastInsertId()
|
||||
return int(id), err
|
||||
}
|
||||
|
||||
func (r *StandardizationRepository) UpdateStandardDocument(ctx context.Context, id int, d models.StandardDocument) error {
|
||||
res, err := r.db.ExecContext(ctx, `
|
||||
UPDATE standard_documents
|
||||
SET wg = ?, project_name = ?, title = ?, doc_ref = ?, status = ?, published_at = ?
|
||||
WHERE id = ?
|
||||
`, d.WG, d.ProjectName, d.Title, d.DocRef, d.Status, d.PublishedAt, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("update standard document: %w", err)
|
||||
}
|
||||
rows, err := res.RowsAffected()
|
||||
if err == nil && rows == 0 {
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *StandardizationRepository) DeleteStandardDocument(ctx context.Context, id int) error {
|
||||
res, err := r.db.ExecContext(ctx, `DELETE FROM standard_documents WHERE id = ?`, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("delete standard document: %w", err)
|
||||
}
|
||||
rows, err := res.RowsAffected()
|
||||
if err == nil && rows == 0 {
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user