material_manage_system/internal/repository/organization.go
2026-09-16 16:29:04 +08:00

178 lines
5.1 KiB
Go

package repository
import (
"errors"
"fmt"
"strings"
"github.com/wmms/wmms/internal/model"
"github.com/wmms/wmms/pkg/database"
)
type OrganizationRepository struct{}
var ErrProtectedRole = errors.New("super administrator role cannot be changed")
func NewOrganizationRepository() *OrganizationRepository { return &OrganizationRepository{} }
func (r *OrganizationRepository) List() ([]model.Organization, error) {
rows, err := database.DB.Query(`SELECT id, code, name, status, default_timezone, created_at, updated_at
FROM organizations ORDER BY id`)
if err != nil {
return nil, err
}
defer rows.Close()
organizations := make([]model.Organization, 0)
for rows.Next() {
var item model.Organization
if err := rows.Scan(&item.ID, &item.Code, &item.Name, &item.Status, &item.DefaultTimezone, &item.CreatedAt, &item.UpdatedAt); err != nil {
return nil, err
}
organizations = append(organizations, item)
}
return organizations, rows.Err()
}
func (r *OrganizationRepository) Create(item *model.Organization) error {
result, err := database.DB.Exec(`INSERT INTO organizations (code, name, status, default_timezone) VALUES (?, ?, ?, ?)`, item.Code, item.Name, item.Status, item.DefaultTimezone)
if err != nil {
return err
}
item.ID, err = result.LastInsertId()
return err
}
func (r *OrganizationRepository) Update(item *model.Organization) error {
_, err := database.DB.Exec(`UPDATE organizations SET name = ?, status = ?, default_timezone = ? WHERE id = ?`, item.Name, item.Status, item.DefaultTimezone, item.ID)
return err
}
func (r *OrganizationRepository) ListRoles() ([]model.Role, error) {
rows, err := database.DB.Query(`SELECT id, code, name, enabled, created_at, updated_at FROM roles ORDER BY id`)
if err != nil {
return nil, err
}
defer rows.Close()
roles := make([]model.Role, 0)
roleIndexes := make(map[int64]int)
for rows.Next() {
var item model.Role
if err := rows.Scan(&item.ID, &item.Code, &item.Name, &item.Enabled, &item.CreatedAt, &item.UpdatedAt); err != nil {
return nil, err
}
item.Permissions = []model.Permission{}
roleIndexes[item.ID] = len(roles)
roles = append(roles, item)
}
if err := rows.Err(); err != nil {
return nil, err
}
permissionRows, err := database.DB.Query(`SELECT rp.role_id, p.id, p.code, p.name
FROM role_permissions rp JOIN permissions p ON p.id = rp.permission_id
ORDER BY rp.role_id, p.code`)
if err != nil {
return nil, err
}
defer permissionRows.Close()
for permissionRows.Next() {
var roleID int64
var permission model.Permission
if err := permissionRows.Scan(&roleID, &permission.ID, &permission.Code, &permission.Name); err != nil {
return nil, err
}
if index, ok := roleIndexes[roleID]; ok {
roles[index].Permissions = append(roles[index].Permissions, permission)
}
}
return roles, permissionRows.Err()
}
func (r *OrganizationRepository) ListPermissions() ([]model.Permission, error) {
rows, err := database.DB.Query(`SELECT id, code, name FROM permissions ORDER BY code`)
if err != nil {
return nil, err
}
defer rows.Close()
permissions := make([]model.Permission, 0)
for rows.Next() {
var permission model.Permission
if err := rows.Scan(&permission.ID, &permission.Code, &permission.Name); err != nil {
return nil, err
}
permissions = append(permissions, permission)
}
return permissions, rows.Err()
}
func (r *OrganizationRepository) UpdateRole(roleID int64, name string, enabled bool, permissionCodes []string) (err error) {
tx, err := database.DB.Begin()
if err != nil {
return err
}
defer func() {
if err != nil {
_ = tx.Rollback()
}
}()
var roleCode string
if err = tx.QueryRow(`SELECT code FROM roles WHERE id = ? FOR UPDATE`, roleID).Scan(&roleCode); err != nil {
return err
}
if roleCode == "super_admin" {
return ErrProtectedRole
}
if _, err = tx.Exec(`UPDATE roles SET name = ?, enabled = ? WHERE id = ?`, name, enabled, roleID); err != nil {
return err
}
if _, err = tx.Exec(`DELETE FROM role_permissions WHERE role_id = ?`, roleID); err != nil {
return err
}
permissionCodes = uniqueStrings(permissionCodes)
if len(permissionCodes) > 0 {
placeholders := strings.TrimSuffix(strings.Repeat("?, ", len(permissionCodes)), ", ")
query := fmt.Sprintf(`INSERT INTO role_permissions (role_id, permission_id)
SELECT ?, id FROM permissions WHERE code IN (%s)`, placeholders)
args := make([]interface{}, 0, len(permissionCodes)+1)
args = append(args, roleID)
for _, code := range permissionCodes {
args = append(args, code)
}
result, execErr := tx.Exec(query, args...)
if execErr != nil {
err = execErr
return err
}
var affected int64
affected, err = result.RowsAffected()
if err != nil {
return err
}
if affected != int64(len(permissionCodes)) {
return fmt.Errorf("one or more permission codes do not exist")
}
}
return tx.Commit()
}
func uniqueStrings(values []string) []string {
seen := make(map[string]struct{}, len(values))
result := make([]string, 0, len(values))
for _, value := range values {
value = strings.TrimSpace(value)
if value == "" {
continue
}
if _, exists := seen[value]; exists {
continue
}
seen[value] = struct{}{}
result = append(result, value)
}
return result
}