sqlx
This commit is contained in:
117
internal/erpserver/repository/system/audit/audit.go
Normal file
117
internal/erpserver/repository/system/audit/audit.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package audit
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"management/internal/erpserver/model/dto"
|
||||
"management/internal/erpserver/model/system"
|
||||
"management/internal/erpserver/repository"
|
||||
"management/internal/pkg/sqldb"
|
||||
|
||||
"github.com/drhin/logger"
|
||||
)
|
||||
|
||||
type store struct {
|
||||
db *repository.Store
|
||||
log *logger.Logger
|
||||
}
|
||||
|
||||
func NewStore(db *repository.Store, log *logger.Logger) system.AuditLogRepository {
|
||||
return &store{
|
||||
db: db,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *store) Create(ctx context.Context, obj *system.AuditLog) error {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
INSERT INTO sys_audit_log(
|
||||
email, start_at, end_at, duration, url, method, parameters,
|
||||
referer_url, os, ip, browser, remark)
|
||||
VALUES (
|
||||
:email, :start_at, :end_at, :duration, :url, :method, :parameters,
|
||||
:referer_url, :os, :ip, :browser, :remark)`
|
||||
|
||||
return sqldb.NamedExecContext(ctx, s.log, s.db.DB(ctx), q, obj)
|
||||
}
|
||||
|
||||
func (s *store) BatchCreate(ctx context.Context, objs []*system.AuditLog) error {
|
||||
if len(objs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
INSERT INTO sys_audit_log(
|
||||
email, start_at, end_at, duration, url, method, parameters,
|
||||
referer_url, os, ip, browser, remark)
|
||||
VALUES (
|
||||
:email, :start_at, :end_at, :duration, :url, :method, :parameters,
|
||||
:referer_url, :os, :ip, :browser, :remark)`
|
||||
|
||||
return sqldb.NamedExecContext(ctx, s.log, s.db.DB(ctx), q, objs)
|
||||
}
|
||||
|
||||
func (s *store) Count(ctx context.Context, filter dto.SearchDto) (int64, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
COUNT(1)
|
||||
FROM
|
||||
sys_audit_log`
|
||||
|
||||
data := map[string]any{}
|
||||
|
||||
buf := bytes.NewBufferString(q)
|
||||
applyFilter(filter, data, buf)
|
||||
|
||||
var count struct {
|
||||
Count int64 `db:"count"`
|
||||
}
|
||||
|
||||
err := sqldb.NamedQueryStruct(ctx, s.log, s.db.DB(ctx), buf.String(), data, &count)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("select count audit: %w", err)
|
||||
}
|
||||
|
||||
return count.Count, nil
|
||||
}
|
||||
|
||||
func (s *store) List(ctx context.Context, filter dto.SearchDto) ([]*system.AuditLog, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
id, created_at, email, start_at, end_at, duration, url,
|
||||
method, parameters, referer_url, os, ip, browser, remark
|
||||
FROM
|
||||
sys_audit_log`
|
||||
|
||||
data := map[string]any{
|
||||
"offset": (filter.Page - 1) * filter.Rows,
|
||||
"rows_per_page": filter.Rows,
|
||||
}
|
||||
|
||||
buf := bytes.NewBufferString(q)
|
||||
applyFilter(filter, data, buf)
|
||||
|
||||
buf.WriteString(" ORDER BY id DESC")
|
||||
buf.WriteString(" LIMIT :rows_per_page OFFSET :offset")
|
||||
|
||||
var audits []system.AuditLog
|
||||
err := sqldb.NamedQuerySlice(ctx, s.log, s.db.DB(ctx), buf.String(), data, &audits)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return toPointer(audits), nil
|
||||
}
|
||||
|
||||
func toPointer(data []system.AuditLog) []*system.AuditLog {
|
||||
var res []*system.AuditLog
|
||||
for _, v := range data {
|
||||
res = append(res, &v)
|
||||
}
|
||||
return res
|
||||
}
|
||||
28
internal/erpserver/repository/system/audit/filter.go
Normal file
28
internal/erpserver/repository/system/audit/filter.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package audit
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
|
||||
"management/internal/erpserver/model/dto"
|
||||
)
|
||||
|
||||
func applyFilter(filter dto.SearchDto, data map[string]any, buf *bytes.Buffer) {
|
||||
var wc []string
|
||||
|
||||
if filter.SearchTimeBegin != "" && filter.SearchTimeEnd == "" {
|
||||
data["start_at"] = filter.SearchTimeBegin
|
||||
data["end_at"] = filter.SearchTimeEnd
|
||||
wc = append(wc, "created_at BETWEEN :start_at AND :end_at")
|
||||
}
|
||||
|
||||
if filter.SearchEmail != "" {
|
||||
data["email"] = filter.SearchEmail
|
||||
wc = append(wc, "email LIKE :email")
|
||||
}
|
||||
|
||||
if len(wc) > 0 {
|
||||
buf.WriteString(" WHERE ")
|
||||
buf.WriteString(strings.Join(wc, " AND "))
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"management/internal/erpserver/model/dto"
|
||||
"management/internal/erpserver/model/system"
|
||||
"management/internal/erpserver/repository"
|
||||
)
|
||||
|
||||
type auditLogRepository struct {
|
||||
repo *repository.Repository
|
||||
}
|
||||
|
||||
func NewAuditLogRepository(repo *repository.Repository) system.AuditLogRepository {
|
||||
return &auditLogRepository{
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *auditLogRepository) Create(ctx context.Context, obj *system.AuditLog) error {
|
||||
return s.repo.DB(ctx).Create(obj).Error
|
||||
}
|
||||
|
||||
func (s *auditLogRepository) BatchCreate(ctx context.Context, objs []*system.AuditLog) error {
|
||||
return s.repo.DB(ctx).Create(objs).Error
|
||||
}
|
||||
|
||||
func (s *auditLogRepository) List(ctx context.Context, q dto.SearchDto) ([]*system.AuditLog, int64, error) {
|
||||
query := s.repo.DB(ctx).
|
||||
Model(&system.AuditLog{}).
|
||||
Where("created_at BETWEEN ? AND ?", q.SearchTimeBegin, q.SearchTimeEnd)
|
||||
if q.SearchEmail != "" {
|
||||
query = query.Where("email LIKE ?", "%"+q.SearchEmail+"%")
|
||||
}
|
||||
|
||||
var count int64
|
||||
err := query.Count(&count).Error
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
var logs []*system.AuditLog
|
||||
err = query.
|
||||
Order("id DESC").
|
||||
Offset((q.Page - 1) * q.Rows).
|
||||
Limit(q.Rows).
|
||||
Find(&logs).
|
||||
Error
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return logs, count, nil
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"management/internal/erpserver/model/dto"
|
||||
"management/internal/erpserver/model/system"
|
||||
"management/internal/erpserver/repository"
|
||||
"management/internal/pkg/database"
|
||||
"management/internal/pkg/know/pearadmin"
|
||||
|
||||
"gorm.io/datatypes"
|
||||
)
|
||||
|
||||
type configRepository struct {
|
||||
repo *repository.Repository
|
||||
}
|
||||
|
||||
func NewConfigRepository(repo *repository.Repository) system.ConfigRepository {
|
||||
return &configRepository{
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *configRepository) Initialize(ctx context.Context) error {
|
||||
_, err := r.GetByKey(ctx, pearadmin.PearKey)
|
||||
if err != nil {
|
||||
if database.IsNoRows(err) {
|
||||
b, e := json.Marshal(pearadmin.PearJson)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
|
||||
s := system.Config{
|
||||
Key: pearadmin.PearKey,
|
||||
Value: datatypes.JSON(b),
|
||||
}
|
||||
return r.Create(ctx, &s)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *configRepository) Create(ctx context.Context, obj *system.Config) error {
|
||||
return r.repo.DB(ctx).Create(obj).Error
|
||||
}
|
||||
|
||||
func (r *configRepository) Update(ctx context.Context, obj *system.Config) error {
|
||||
return r.repo.DB(ctx).Save(obj).Error
|
||||
}
|
||||
|
||||
func (r *configRepository) Get(ctx context.Context, id int32) (*system.Config, error) {
|
||||
var obj system.Config
|
||||
err := r.repo.DB(ctx).First(&obj, id).Error
|
||||
if err != nil {
|
||||
if database.IsNoRows(err) {
|
||||
return nil, fmt.Errorf("config %d not found: %w", id, err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &obj, nil
|
||||
}
|
||||
|
||||
func (r *configRepository) GetByKey(ctx context.Context, key string) (*system.Config, error) {
|
||||
var obj system.Config
|
||||
err := r.repo.DB(ctx).Where("key = ?", key).First(&obj).Error
|
||||
if err != nil {
|
||||
if database.IsNoRows(err) {
|
||||
return nil, fmt.Errorf("config key %s not found: %w", key, err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &obj, nil
|
||||
}
|
||||
|
||||
func (r *configRepository) GetValueByKey(ctx context.Context, key string) ([]byte, error) {
|
||||
var obj system.Config
|
||||
err := r.repo.DB(ctx).Where("key = ?", key).First(&obj).Error
|
||||
if err != nil {
|
||||
if database.IsNoRows(err) {
|
||||
return nil, fmt.Errorf("config key value %s not found: %w", key, err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return obj.Value, nil
|
||||
}
|
||||
|
||||
func (r *configRepository) List(ctx context.Context, q dto.SearchDto) ([]*system.Config, int64, error) {
|
||||
query := r.repo.DB(ctx).
|
||||
Model(&system.Config{}).
|
||||
Where("created_at BETWEEN ? AND ?", q.SearchTimeBegin, q.SearchTimeEnd)
|
||||
|
||||
var count int64
|
||||
err := query.Count(&count).Error
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
var configs []*system.Config
|
||||
err = query.
|
||||
Order("id DESC").
|
||||
Offset((q.Page - 1) * q.Rows).
|
||||
Limit(q.Rows).
|
||||
Find(&configs).
|
||||
Error
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return configs, count, nil
|
||||
}
|
||||
177
internal/erpserver/repository/system/config/config.go
Normal file
177
internal/erpserver/repository/system/config/config.go
Normal file
@@ -0,0 +1,177 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"management/internal/erpserver/model/dto"
|
||||
"management/internal/erpserver/model/system"
|
||||
"management/internal/erpserver/repository"
|
||||
"management/internal/pkg/database"
|
||||
"management/internal/pkg/know/pearadmin"
|
||||
"management/internal/pkg/sqldb"
|
||||
|
||||
"github.com/drhin/logger"
|
||||
"gorm.io/datatypes"
|
||||
)
|
||||
|
||||
type store struct {
|
||||
db *repository.Store
|
||||
log *logger.Logger
|
||||
}
|
||||
|
||||
func NewStore(db *repository.Store, log *logger.Logger) system.ConfigRepository {
|
||||
return &store{
|
||||
db: db,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *store) Initialize(ctx context.Context) error {
|
||||
_, err := s.GetByKey(ctx, pearadmin.PearKey)
|
||||
if err != nil {
|
||||
if database.IsNoRows(err) {
|
||||
b, e := json.Marshal(pearadmin.PearJson)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
|
||||
return s.Create(ctx, &system.Config{
|
||||
Key: pearadmin.PearKey,
|
||||
Value: datatypes.JSON(b),
|
||||
})
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *store) Create(ctx context.Context, obj *system.Config) error {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
INSERT INTO sys_config (
|
||||
key, value
|
||||
) VALUES (
|
||||
:key, :value
|
||||
);`
|
||||
|
||||
return sqldb.NamedExecContext(ctx, s.log, s.db.DB(ctx), q, obj)
|
||||
}
|
||||
|
||||
func (s *store) Update(ctx context.Context, obj *system.Config) error {
|
||||
const q = `
|
||||
UPDATE sys_config
|
||||
SET key = :key,
|
||||
value = :value,
|
||||
updated_at = :updated_at
|
||||
WHERE id = :id;`
|
||||
|
||||
return sqldb.NamedExecContext(ctx, s.log, s.db.DB(ctx), q, obj)
|
||||
}
|
||||
|
||||
func (s *store) Get(ctx context.Context, id int32) (*system.Config, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
id, key, value, created_at, updated_at
|
||||
FROM
|
||||
sys_config
|
||||
WHERE
|
||||
id = :id;`
|
||||
|
||||
data := map[string]any{
|
||||
"id": id,
|
||||
}
|
||||
|
||||
var config system.Config
|
||||
err := sqldb.NamedQueryStruct(ctx, s.log, s.db.DB(ctx), q, data, &config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("select id config: %w", err)
|
||||
}
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
func (s *store) GetByKey(ctx context.Context, key string) (*system.Config, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
id, key, value, created_at, updated_at
|
||||
FROM
|
||||
sys_config
|
||||
WHERE
|
||||
key = :key;`
|
||||
|
||||
data := map[string]any{
|
||||
"key": key,
|
||||
}
|
||||
|
||||
var config system.Config
|
||||
err := sqldb.NamedQueryStruct(ctx, s.log, s.db.DB(ctx), q, data, &config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("select key config: %w", err)
|
||||
}
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
func (s *store) Count(ctx context.Context, filter dto.SearchDto) (int64, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
COUNT(1)
|
||||
FROM
|
||||
sys_config`
|
||||
|
||||
data := map[string]any{}
|
||||
|
||||
buf := bytes.NewBufferString(q)
|
||||
applyFilter(filter, data, buf)
|
||||
|
||||
var count struct {
|
||||
Count int64 `db:"count"`
|
||||
}
|
||||
|
||||
err := sqldb.NamedQueryStruct(ctx, s.log, s.db.DB(ctx), buf.String(), data, &count)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("select count config: %w", err)
|
||||
}
|
||||
|
||||
return count.Count, nil
|
||||
}
|
||||
func (s *store) List(ctx context.Context, filter dto.SearchDto) ([]*system.Config, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
id, key, value, created_at, updated_at
|
||||
FROM
|
||||
sys_config`
|
||||
|
||||
data := map[string]any{
|
||||
"offset": (filter.Page - 1) * filter.Rows,
|
||||
"rows_per_page": filter.Rows,
|
||||
}
|
||||
|
||||
buf := bytes.NewBufferString(q)
|
||||
applyFilter(filter, data, buf)
|
||||
|
||||
buf.WriteString(" ORDER BY id DESC")
|
||||
buf.WriteString(" LIMIT :rows_per_page OFFSET :offset")
|
||||
|
||||
var configs []system.Config
|
||||
err := sqldb.NamedQuerySlice(ctx, s.log, s.db.DB(ctx), buf.String(), data, &configs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return toPointer(configs), nil
|
||||
}
|
||||
|
||||
func toPointer(data []system.Config) []*system.Config {
|
||||
var res []*system.Config
|
||||
for _, v := range data {
|
||||
res = append(res, &v)
|
||||
}
|
||||
return res
|
||||
}
|
||||
23
internal/erpserver/repository/system/config/filter.go
Normal file
23
internal/erpserver/repository/system/config/filter.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
|
||||
"management/internal/erpserver/model/dto"
|
||||
)
|
||||
|
||||
func applyFilter(filter dto.SearchDto, data map[string]any, buf *bytes.Buffer) {
|
||||
var wc []string
|
||||
|
||||
if filter.SearchTimeBegin != "" && filter.SearchTimeEnd == "" {
|
||||
data["start_at"] = filter.SearchTimeBegin
|
||||
data["end_at"] = filter.SearchTimeEnd
|
||||
wc = append(wc, "created_at BETWEEN :start_at AND :end_at")
|
||||
}
|
||||
|
||||
if len(wc) > 0 {
|
||||
buf.WriteString(" WHERE ")
|
||||
buf.WriteString(strings.Join(wc, " AND "))
|
||||
}
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"management/internal/erpserver/model/dto"
|
||||
"management/internal/erpserver/model/system"
|
||||
"management/internal/erpserver/repository"
|
||||
"management/internal/pkg/database"
|
||||
)
|
||||
|
||||
type departmentRepository struct {
|
||||
repo *repository.Repository
|
||||
}
|
||||
|
||||
func NewDepartmentRepository(repo *repository.Repository) system.DepartmentRepository {
|
||||
return &departmentRepository{
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *departmentRepository) Initialize(ctx context.Context) error {
|
||||
var count int64
|
||||
if err := r.repo.DB(ctx).Model(&system.Department{}).Count(&count).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if count == 0 {
|
||||
obj := system.Department{
|
||||
Name: "公司",
|
||||
ParentID: 0,
|
||||
ParentPath: ",0,",
|
||||
Status: 0,
|
||||
Sort: 6666,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
return r.Create(ctx, &obj)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *departmentRepository) Create(ctx context.Context, obj *system.Department) error {
|
||||
return r.repo.DB(ctx).Create(obj).Error
|
||||
}
|
||||
|
||||
func (r *departmentRepository) Update(ctx context.Context, obj *system.Department) error {
|
||||
return r.repo.DB(ctx).Save(obj).Error
|
||||
}
|
||||
|
||||
func (r *departmentRepository) Get(ctx context.Context, id int32) (*system.Department, error) {
|
||||
var obj system.Department
|
||||
err := r.repo.DB(ctx).First(&obj, id).Error
|
||||
if err != nil {
|
||||
if database.IsNoRows(err) {
|
||||
return nil, fmt.Errorf("department %d not found: %w", id, err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &obj, nil
|
||||
}
|
||||
|
||||
func (r *departmentRepository) All(ctx context.Context) ([]*system.Department, error) {
|
||||
var departs []*system.Department
|
||||
err := r.repo.DB(ctx).Find(&departs).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return departs, nil
|
||||
}
|
||||
|
||||
func (r *departmentRepository) List(ctx context.Context, q dto.SearchDto) ([]*system.Department, int64, error) {
|
||||
query := r.repo.DB(ctx).
|
||||
Model(&system.Department{}).
|
||||
Where("created_at BETWEEN ? AND ?", q.SearchTimeBegin, q.SearchTimeEnd)
|
||||
if q.SearchID != 0 {
|
||||
query = query.Where("id = ?", q.SearchID)
|
||||
}
|
||||
if q.SearchParentID != 0 && q.SearchParentID != 1 {
|
||||
query = query.Where("parent_id = ?", q.SearchParentID)
|
||||
}
|
||||
if q.SearchName != "" {
|
||||
query = query.Where("name LIKE ?", "%"+q.SearchName+"%")
|
||||
}
|
||||
if q.SearchStatus != 9999 {
|
||||
query = query.Where("status = ?", q.SearchStatus)
|
||||
}
|
||||
|
||||
var count int64
|
||||
err := query.Count(&count).Error
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
var departs []*system.Department
|
||||
err = query.
|
||||
Order("id DESC").
|
||||
Offset((q.Page - 1) * q.Rows).
|
||||
Limit(q.Rows).
|
||||
Find(&departs).Error
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return departs, count, nil
|
||||
}
|
||||
|
||||
func (r *departmentRepository) RebuildParentPath(ctx context.Context) error {
|
||||
query := `UPDATE sys_department AS tm
|
||||
SET parent_path = (SELECT ',' || string_agg(cast(t.parent_id AS VARCHAR), ',') || ','
|
||||
FROM (WITH RECURSIVE temp (id, parent_id) AS (SELECT id, tm.parent_id
|
||||
FROM sys_department
|
||||
WHERE id = tm.id
|
||||
UNION ALL
|
||||
SELECT sys_department.id, sys_department.parent_id
|
||||
FROM sys_department,
|
||||
temp
|
||||
WHERE sys_department.id = temp.parent_id)
|
||||
SELECT id, parent_id
|
||||
FROM temp
|
||||
ORDER BY id) AS t)
|
||||
WHERE tm.status = 0;`
|
||||
return r.repo.DB(ctx).Exec(query).Error
|
||||
}
|
||||
195
internal/erpserver/repository/system/department/department.go
Normal file
195
internal/erpserver/repository/system/department/department.go
Normal file
@@ -0,0 +1,195 @@
|
||||
package department
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"management/internal/erpserver/model/dto"
|
||||
"management/internal/erpserver/model/system"
|
||||
"management/internal/erpserver/repository"
|
||||
"management/internal/pkg/sqldb"
|
||||
|
||||
"github.com/drhin/logger"
|
||||
)
|
||||
|
||||
type store struct {
|
||||
db *repository.Store
|
||||
log *logger.Logger
|
||||
}
|
||||
|
||||
func NewStore(db *repository.Store, log *logger.Logger) system.DepartmentRepository {
|
||||
return &store{
|
||||
db: db,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *store) Initialize(ctx context.Context) error {
|
||||
count, err := s.Count(ctx, dto.SearchDto{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if count == 0 {
|
||||
obj := system.Department{
|
||||
Name: "公司",
|
||||
ParentID: 0,
|
||||
ParentPath: ",0,",
|
||||
Status: 0,
|
||||
Sort: 6666,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
return s.Create(ctx, &obj)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *store) Create(ctx context.Context, obj *system.Department) error {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
INSERT INTO sys_department (
|
||||
name, parent_id, parent_path, status, sort
|
||||
) VALUES (
|
||||
:name, :parent_id, :parent_path, :status, :sort
|
||||
);`
|
||||
|
||||
return sqldb.NamedExecContext(ctx, s.log, s.db.DB(ctx), q, obj)
|
||||
}
|
||||
|
||||
func (s *store) Update(ctx context.Context, obj *system.Department) error {
|
||||
const q = `
|
||||
UPDATE sys_department
|
||||
SET name = :name,
|
||||
parent_id = :parent_id,
|
||||
parent_path = :parent_path,
|
||||
status = :status,
|
||||
sort = :sort,
|
||||
updated_at = :updated_at
|
||||
WHERE id = :id;`
|
||||
|
||||
return sqldb.NamedExecContext(ctx, s.log, s.db.DB(ctx), q, obj)
|
||||
}
|
||||
|
||||
func (s *store) Get(ctx context.Context, id int32) (*system.Department, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
id, name, parent_id, parent_path, status, sort, created_at, updated_at
|
||||
FROM
|
||||
sys_department
|
||||
WHERE
|
||||
id = :id;`
|
||||
|
||||
data := map[string]any{
|
||||
"id": id,
|
||||
}
|
||||
|
||||
var depart system.Department
|
||||
err := sqldb.NamedQueryStruct(ctx, s.log, s.db.DB(ctx), q, data, &depart)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("select id department: %w", err)
|
||||
}
|
||||
|
||||
return &depart, nil
|
||||
}
|
||||
|
||||
func (s *store) All(ctx context.Context) ([]*system.Department, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
id, name, parent_id, parent_path, status, sort, created_at, updated_at
|
||||
FROM
|
||||
sys_department;`
|
||||
|
||||
data := map[string]any{}
|
||||
|
||||
var departs []system.Department
|
||||
err := sqldb.NamedQuerySlice(ctx, s.log, s.db.DB(ctx), q, data, &departs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("select all department: %w", err)
|
||||
}
|
||||
|
||||
return toPointer(departs), nil
|
||||
}
|
||||
|
||||
func (s *store) Count(ctx context.Context, filter dto.SearchDto) (int64, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
COUNT(1)
|
||||
FROM
|
||||
sys_department`
|
||||
|
||||
data := map[string]any{}
|
||||
|
||||
buf := bytes.NewBufferString(q)
|
||||
applyFilter(filter, data, buf)
|
||||
|
||||
var count struct {
|
||||
Count int64 `db:"count"`
|
||||
}
|
||||
|
||||
err := sqldb.NamedQueryStruct(ctx, s.log, s.db.DB(ctx), buf.String(), data, &count)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("select count department: %w", err)
|
||||
}
|
||||
|
||||
return count.Count, nil
|
||||
}
|
||||
|
||||
func (s *store) List(ctx context.Context, filter dto.SearchDto) ([]*system.Department, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
id, name, parent_id, parent_path, status, sort, created_at, updated_at
|
||||
FROM
|
||||
sys_department`
|
||||
|
||||
data := map[string]any{
|
||||
"offset": (filter.Page - 1) * filter.Rows,
|
||||
"rows_per_page": filter.Rows,
|
||||
}
|
||||
|
||||
buf := bytes.NewBufferString(q)
|
||||
applyFilter(filter, data, buf)
|
||||
|
||||
buf.WriteString(" ORDER BY id DESC")
|
||||
buf.WriteString(" LIMIT :rows_per_page OFFSET :offset")
|
||||
|
||||
var departs []system.Department
|
||||
err := sqldb.NamedQuerySlice(ctx, s.log, s.db.DB(ctx), buf.String(), data, &departs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return toPointer(departs), nil
|
||||
}
|
||||
|
||||
func (s *store) RebuildParentPath(ctx context.Context) error {
|
||||
query := `
|
||||
UPDATE sys_department AS tm
|
||||
SET parent_path = (SELECT ',' || string_agg(cast(t.parent_id AS VARCHAR), ',') || ','
|
||||
FROM (WITH RECURSIVE temp (id, parent_id) AS (SELECT id, tm.parent_id
|
||||
FROM sys_department
|
||||
WHERE id = tm.id
|
||||
UNION ALL
|
||||
SELECT sys_department.id, sys_department.parent_id
|
||||
FROM sys_department,
|
||||
temp
|
||||
WHERE sys_department.id = temp.parent_id)
|
||||
SELECT id, parent_id
|
||||
FROM temp
|
||||
ORDER BY id) AS t)
|
||||
WHERE tm.status = 0;`
|
||||
return sqldb.NamedExecContext(ctx, s.log, s.db.DB(ctx), query, nil)
|
||||
}
|
||||
|
||||
func toPointer(data []system.Department) []*system.Department {
|
||||
var res []*system.Department
|
||||
for _, v := range data {
|
||||
res = append(res, &v)
|
||||
}
|
||||
return res
|
||||
}
|
||||
48
internal/erpserver/repository/system/department/filter.go
Normal file
48
internal/erpserver/repository/system/department/filter.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package department
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
|
||||
"management/internal/erpserver/model/dto"
|
||||
)
|
||||
|
||||
func applyFilter(filter dto.SearchDto, data map[string]any, buf *bytes.Buffer) {
|
||||
var wc []string
|
||||
|
||||
if filter.SearchTimeBegin != "" && filter.SearchTimeEnd == "" {
|
||||
data["start_at"] = filter.SearchTimeBegin
|
||||
data["end_at"] = filter.SearchTimeEnd
|
||||
wc = append(wc, "created_at BETWEEN :start_at AND :end_at")
|
||||
}
|
||||
|
||||
if filter.SearchEmail != "" {
|
||||
data["email"] = filter.SearchEmail
|
||||
wc = append(wc, "email LIKE :email")
|
||||
}
|
||||
|
||||
if filter.SearchID != 0 {
|
||||
data["id"] = filter.SearchID
|
||||
wc = append(wc, "id = :id")
|
||||
}
|
||||
|
||||
if filter.SearchParentID != 0 && filter.SearchParentID != 1 {
|
||||
data["parent_id"] = filter.SearchParentID
|
||||
wc = append(wc, "parent_id = :parent_id")
|
||||
}
|
||||
|
||||
if filter.SearchName != "" {
|
||||
data["name"] = filter.SearchName
|
||||
wc = append(wc, "name LIKE :name")
|
||||
}
|
||||
|
||||
if filter.SearchStatus != 9999 {
|
||||
data["status"] = filter.SearchStatus
|
||||
wc = append(wc, "status = :status")
|
||||
}
|
||||
|
||||
if len(wc) > 0 {
|
||||
buf.WriteString(" WHERE ")
|
||||
buf.WriteString(strings.Join(wc, " AND "))
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"management/internal/erpserver/model/dto"
|
||||
"management/internal/erpserver/model/system"
|
||||
"management/internal/erpserver/repository"
|
||||
)
|
||||
|
||||
type loginLogRepository struct {
|
||||
repo *repository.Repository
|
||||
}
|
||||
|
||||
func NewLoginLogRepository(repo *repository.Repository) system.LoginLogRepository {
|
||||
return &loginLogRepository{
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *loginLogRepository) Create(ctx context.Context, obj *system.LoginLog) error {
|
||||
return s.repo.DB(ctx).Create(obj).Error
|
||||
}
|
||||
|
||||
func (s *loginLogRepository) GetLatest(ctx context.Context, email string) ([]*system.LoginLog, error) {
|
||||
var logs []*system.LoginLog
|
||||
err := s.repo.DB(ctx).
|
||||
Where("email = ?", email).
|
||||
Order("id DESC").
|
||||
Limit(2).
|
||||
Find(&logs).
|
||||
Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return logs, nil
|
||||
}
|
||||
|
||||
func (s *loginLogRepository) List(ctx context.Context, q dto.SearchDto) ([]*system.LoginLog, int64, error) {
|
||||
query := s.repo.DB(ctx).
|
||||
Model(&system.LoginLog{}).
|
||||
Where("created_at BETWEEN ? AND ?", q.SearchTimeBegin, q.SearchTimeEnd)
|
||||
if q.SearchEmail != "" {
|
||||
query = query.Where("email LIKE ?", "%"+q.SearchEmail+"%")
|
||||
}
|
||||
|
||||
var count int64
|
||||
err := query.Count(&count).Error
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
var logs []*system.LoginLog
|
||||
err = query.
|
||||
Order("id DESC").
|
||||
Offset((q.Page - 1) * q.Rows).
|
||||
Limit(q.Rows).
|
||||
Find(&logs).
|
||||
Error
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return logs, count, nil
|
||||
}
|
||||
|
||||
func (s *loginLogRepository) Count(ctx context.Context, email string) (int64, error) {
|
||||
var count int64
|
||||
err := s.repo.DB(ctx).
|
||||
Model(&system.LoginLog{}).
|
||||
Where("email = ?", email).
|
||||
Count(&count).
|
||||
Error
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
28
internal/erpserver/repository/system/loginlog/filter.go
Normal file
28
internal/erpserver/repository/system/loginlog/filter.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package loginlog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
|
||||
"management/internal/erpserver/model/dto"
|
||||
)
|
||||
|
||||
func applyFilter(filter dto.SearchDto, data map[string]any, buf *bytes.Buffer) {
|
||||
var wc []string
|
||||
|
||||
if filter.SearchTimeBegin != "" && filter.SearchTimeEnd == "" {
|
||||
data["start_at"] = filter.SearchTimeBegin
|
||||
data["end_at"] = filter.SearchTimeEnd
|
||||
wc = append(wc, "created_at BETWEEN :start_at AND :end_at")
|
||||
}
|
||||
|
||||
if filter.SearchEmail != "" {
|
||||
data["email"] = filter.SearchEmail
|
||||
wc = append(wc, "email LIKE :email")
|
||||
}
|
||||
|
||||
if len(wc) > 0 {
|
||||
buf.WriteString(" WHERE ")
|
||||
buf.WriteString(strings.Join(wc, " AND "))
|
||||
}
|
||||
}
|
||||
123
internal/erpserver/repository/system/loginlog/login_log.go
Normal file
123
internal/erpserver/repository/system/loginlog/login_log.go
Normal file
@@ -0,0 +1,123 @@
|
||||
package loginlog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"management/internal/erpserver/model/dto"
|
||||
"management/internal/erpserver/model/system"
|
||||
"management/internal/erpserver/repository"
|
||||
"management/internal/pkg/sqldb"
|
||||
|
||||
"github.com/drhin/logger"
|
||||
)
|
||||
|
||||
type store struct {
|
||||
db *repository.Store
|
||||
log *logger.Logger
|
||||
}
|
||||
|
||||
func NewStore(db *repository.Store, log *logger.Logger) system.LoginLogRepository {
|
||||
return &store{
|
||||
db: db,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *store) Create(ctx context.Context, obj *system.LoginLog) error {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
INSERT INTO sys_user_login_log (
|
||||
email, is_success, message, referer_url, url, os, ip, browser
|
||||
) VALUES (
|
||||
:email, :is_success, :message, :referer_url, :url, :os, :ip, :browser
|
||||
)`
|
||||
|
||||
return sqldb.NamedExecContext(ctx, s.log, s.db.DB(ctx), q, obj)
|
||||
}
|
||||
|
||||
func (s *store) GetLatest(ctx context.Context, email string) ([]*system.LoginLog, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
id, created_at, email, is_success, message, referer_url, url, os, ip, browser
|
||||
FROM
|
||||
sys_user_login_log
|
||||
WHERE
|
||||
email = :email
|
||||
ORDER BY
|
||||
id DESC
|
||||
LIMIT 2;`
|
||||
|
||||
data := map[string]any{
|
||||
"email": email,
|
||||
}
|
||||
|
||||
var logs []system.LoginLog
|
||||
err := sqldb.NamedQuerySlice(ctx, s.log, s.db.DB(ctx), q, data, &logs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return toPointer(logs), nil
|
||||
}
|
||||
|
||||
func (s *store) Count(ctx context.Context, filter dto.SearchDto) (int64, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
COUNT(1)
|
||||
FROM
|
||||
sys_user_login_log`
|
||||
|
||||
data := map[string]any{}
|
||||
|
||||
buf := bytes.NewBufferString(q)
|
||||
applyFilter(filter, data, buf)
|
||||
|
||||
var count struct {
|
||||
Count int64 `db:"count"`
|
||||
}
|
||||
|
||||
err := sqldb.NamedQueryStruct(ctx, s.log, s.db.DB(ctx), buf.String(), data, &count)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("select count login log: %w", err)
|
||||
}
|
||||
|
||||
return count.Count, nil
|
||||
}
|
||||
|
||||
func (s *store) List(ctx context.Context, filter dto.SearchDto) ([]*system.LoginLog, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
id, created_at, email, is_success, message, referer_url, url, os, ip, browser
|
||||
FROM
|
||||
sys_user_login_log`
|
||||
|
||||
data := map[string]any{
|
||||
"offset": (filter.Page - 1) * filter.Rows,
|
||||
"rows_per_page": filter.Rows,
|
||||
}
|
||||
|
||||
buf := bytes.NewBufferString(q)
|
||||
applyFilter(filter, data, buf)
|
||||
|
||||
buf.WriteString(" ORDER BY id DESC")
|
||||
buf.WriteString(" LIMIT :rows_per_page OFFSET :offset")
|
||||
|
||||
var logs []system.LoginLog
|
||||
err := sqldb.NamedQuerySlice(ctx, s.log, s.db.DB(ctx), buf.String(), data, &logs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return toPointer(logs), nil
|
||||
}
|
||||
|
||||
func toPointer(data []system.LoginLog) []*system.LoginLog {
|
||||
var res []*system.LoginLog
|
||||
for _, v := range data {
|
||||
res = append(res, &v)
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"management/internal/erpserver/model/system"
|
||||
"management/internal/erpserver/repository"
|
||||
"management/internal/pkg/database"
|
||||
)
|
||||
|
||||
type menuRepository struct {
|
||||
repo *repository.Repository
|
||||
}
|
||||
|
||||
func NewMenuRepository(repo *repository.Repository) system.MenuRepository {
|
||||
return &menuRepository{
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *menuRepository) Create(ctx context.Context, obj *system.Menu) (*system.Menu, error) {
|
||||
err := r.repo.DB(ctx).Create(obj).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func (r *menuRepository) Update(ctx context.Context, obj *system.Menu) error {
|
||||
return r.repo.DB(ctx).Save(obj).Error
|
||||
}
|
||||
|
||||
func (r *menuRepository) Get(ctx context.Context, id int32) (*system.Menu, error) {
|
||||
var menu system.Menu
|
||||
err := r.repo.DB(ctx).Where("id = ?", id).First(&menu).Error
|
||||
if err != nil {
|
||||
if database.IsNoRows(err) {
|
||||
return nil, fmt.Errorf("menu %d not found: %w", id, err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &menu, nil
|
||||
}
|
||||
|
||||
func (r *menuRepository) GetByUrl(ctx context.Context, url string) (*system.Menu, error) {
|
||||
var menu system.Menu
|
||||
err := r.repo.DB(ctx).Where("url = ?", url).First(&menu).Error
|
||||
if err != nil {
|
||||
if database.IsNoRows(err) {
|
||||
return nil, fmt.Errorf("menu by url %s not found: %w", url, err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &menu, nil
|
||||
}
|
||||
|
||||
func (r *menuRepository) All(ctx context.Context) ([]*system.Menu, error) {
|
||||
var menus []*system.Menu
|
||||
err := r.repo.DB(ctx).Find(&menus).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return menus, nil
|
||||
}
|
||||
|
||||
func (r *menuRepository) RebuildParentPath(ctx context.Context) error {
|
||||
query := `UPDATE sys_menu AS tm
|
||||
SET parent_path = (SELECT ',' || string_agg(cast(t.parent_id AS VARCHAR), ',') || ','
|
||||
FROM (WITH RECURSIVE temp (id, parent_id) AS (SELECT id, tm.parent_id
|
||||
FROM sys_menu
|
||||
WHERE id = tm.id
|
||||
UNION ALL
|
||||
SELECT sys_menu.id, sys_menu.parent_id
|
||||
FROM sys_menu,
|
||||
temp
|
||||
WHERE sys_menu.id = temp.parent_id)
|
||||
SELECT id, parent_id
|
||||
FROM temp
|
||||
ORDER BY id) AS t)
|
||||
WHERE tm.status = 0;`
|
||||
return r.repo.DB(ctx).Exec(query).Error
|
||||
}
|
||||
179
internal/erpserver/repository/system/menu/menu.go
Normal file
179
internal/erpserver/repository/system/menu/menu.go
Normal file
@@ -0,0 +1,179 @@
|
||||
package menu
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"management/internal/erpserver/model/system"
|
||||
"management/internal/erpserver/repository"
|
||||
"management/internal/pkg/sqldb"
|
||||
|
||||
"github.com/drhin/logger"
|
||||
)
|
||||
|
||||
type store struct {
|
||||
db *repository.Store
|
||||
log *logger.Logger
|
||||
}
|
||||
|
||||
func NewStore(db *repository.Store, log *logger.Logger) system.MenuRepository {
|
||||
return &store{
|
||||
db: db,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *store) Create(ctx context.Context, obj *system.Menu) (*system.Menu, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
INSERT INTO sys_menu (
|
||||
name, display_name, url, type, parent_id, parent_path, avatar, style, visible, is_list, status, sort
|
||||
) VALUES (
|
||||
:name, :display_name, :url, :type, :parent_id, :parent_path, :avatar, :style, :visible, :is_list, :status, :sort
|
||||
);`
|
||||
|
||||
err := sqldb.NamedExecContext(ctx, s.log, s.db.DB(ctx), q, obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func (s *store) Update(ctx context.Context, obj *system.Menu) error {
|
||||
const q = `
|
||||
UPDATE sys_menu
|
||||
SET name = :name,
|
||||
display_name = :display_name,
|
||||
url = :url,
|
||||
type = :type,
|
||||
parent_id = :parent_id,
|
||||
parent_path = :parent_path,
|
||||
avatar = :avatar,
|
||||
style = :style,
|
||||
visible = :visible,
|
||||
is_list = :is_list,
|
||||
status = :status,
|
||||
sort = :sort,
|
||||
updated_at = :updated_at
|
||||
WHERE id = :id;`
|
||||
|
||||
return sqldb.NamedExecContext(ctx, s.log, s.db.DB(ctx), q, obj)
|
||||
}
|
||||
|
||||
func (s *store) Get(ctx context.Context, id int32) (*system.Menu, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
id, name, display_name, url, type, parent_id, parent_path, avatar, style,
|
||||
visible, is_list, status, sort, created_at, updated_at
|
||||
FROM
|
||||
sys_menu
|
||||
WHERE
|
||||
id = :id;`
|
||||
|
||||
data := map[string]any{
|
||||
"id": id,
|
||||
}
|
||||
|
||||
var menu system.Menu
|
||||
err := sqldb.NamedQueryStruct(ctx, s.log, s.db.DB(ctx), q, data, &menu)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("select id menu: %w", err)
|
||||
}
|
||||
|
||||
return &menu, nil
|
||||
}
|
||||
|
||||
func (s *store) GetByUrl(ctx context.Context, url string) (*system.Menu, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
id, name, display_name, url, type, parent_id, parent_path, avatar, style,
|
||||
visible, is_list, status, sort, created_at, updated_at
|
||||
FROM
|
||||
sys_menu
|
||||
WHERE
|
||||
url = :url;`
|
||||
|
||||
data := map[string]any{
|
||||
"url": url,
|
||||
}
|
||||
|
||||
var menu system.Menu
|
||||
err := sqldb.NamedQueryStruct(ctx, s.log, s.db.DB(ctx), q, data, &menu)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("select id menu: %w", err)
|
||||
}
|
||||
|
||||
return &menu, nil
|
||||
}
|
||||
|
||||
func (s *store) All(ctx context.Context) ([]*system.Menu, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
id, name, display_name, url, type, parent_id, parent_path, avatar, style,
|
||||
visible, is_list, status, sort, created_at, updated_at
|
||||
FROM
|
||||
sys_menu;`
|
||||
|
||||
data := map[string]any{}
|
||||
|
||||
var menus []system.Menu
|
||||
err := sqldb.NamedQuerySlice(ctx, s.log, s.db.DB(ctx), q, data, &menus)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("select all menu: %w", err)
|
||||
}
|
||||
|
||||
return toPointer(menus), nil
|
||||
}
|
||||
|
||||
func (s *store) Count(ctx context.Context) (int64, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
COUNT(1)
|
||||
FROM
|
||||
sys_menu`
|
||||
|
||||
data := map[string]any{}
|
||||
|
||||
var count struct {
|
||||
Count int64 `db:"count"`
|
||||
}
|
||||
|
||||
err := sqldb.NamedQueryStruct(ctx, s.log, s.db.DB(ctx), q, data, &count)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("select count menu: %w", err)
|
||||
}
|
||||
|
||||
return count.Count, nil
|
||||
}
|
||||
|
||||
func (s *store) RebuildParentPath(ctx context.Context) error {
|
||||
query := `
|
||||
UPDATE sys_menu AS tm
|
||||
SET parent_path = (SELECT ',' || string_agg(cast(t.parent_id AS VARCHAR), ',') || ','
|
||||
FROM (WITH RECURSIVE temp (id, parent_id) AS (SELECT id, tm.parent_id
|
||||
FROM sys_menu
|
||||
WHERE id = tm.id
|
||||
UNION ALL
|
||||
SELECT sys_menu.id, sys_menu.parent_id
|
||||
FROM sys_menu,
|
||||
temp
|
||||
WHERE sys_menu.id = temp.parent_id)
|
||||
SELECT id, parent_id
|
||||
FROM temp
|
||||
ORDER BY id) AS t)
|
||||
WHERE tm.status = 0;`
|
||||
return sqldb.NamedExecContext(ctx, s.log, s.db.DB(ctx), query, nil)
|
||||
}
|
||||
|
||||
func toPointer(data []system.Menu) []*system.Menu {
|
||||
var res []*system.Menu
|
||||
for _, v := range data {
|
||||
res = append(res, &v)
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package system
|
||||
package menu
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -10,16 +10,17 @@ import (
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
var count int64
|
||||
if err := r.repo.DB(ctx).Model(&system.Menu{}).Count(&count).Error; err != nil {
|
||||
func (s *store) Initialize(ctx context.Context) error {
|
||||
count, err := s.Count(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
sys, err := r.Create(ctx, &system.Menu{
|
||||
sys, err := s.Create(ctx, &system.Menu{
|
||||
Name: "系统管理",
|
||||
DisplayName: "系统管理",
|
||||
Url: uuid.Must(uuid.NewRandom()).String(),
|
||||
@@ -39,7 +40,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
accountPermission, err := r.Create(ctx, &system.Menu{
|
||||
accountPermission, err := s.Create(ctx, &system.Menu{
|
||||
Name: "账户权限",
|
||||
DisplayName: "账户权限",
|
||||
Url: uuid.Must(uuid.NewRandom()).String(),
|
||||
@@ -59,7 +60,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
systemMenu, err := r.Create(ctx, &system.Menu{
|
||||
systemMenu, err := s.Create(ctx, &system.Menu{
|
||||
Name: "菜单管理",
|
||||
DisplayName: "菜单管理",
|
||||
Url: "/system/menu/list",
|
||||
@@ -79,7 +80,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
systemRole, err := r.Create(ctx, &system.Menu{
|
||||
systemRole, err := s.Create(ctx, &system.Menu{
|
||||
Name: "角色管理",
|
||||
DisplayName: "角色管理",
|
||||
Url: "/system/role/list",
|
||||
@@ -99,7 +100,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
systemDepartment, err := r.Create(ctx, &system.Menu{
|
||||
systemDepartment, err := s.Create(ctx, &system.Menu{
|
||||
Name: "部门管理",
|
||||
DisplayName: "部门管理",
|
||||
Url: "/system/department/list",
|
||||
@@ -119,7 +120,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
systemUser, err := r.Create(ctx, &system.Menu{
|
||||
systemUser, err := s.Create(ctx, &system.Menu{
|
||||
Name: "用户管理",
|
||||
DisplayName: "用户管理",
|
||||
Url: "/system/user/list",
|
||||
@@ -139,7 +140,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "登陆日志",
|
||||
DisplayName: "登陆日志",
|
||||
Url: "/system/login_log/list",
|
||||
@@ -159,7 +160,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "审计日志",
|
||||
DisplayName: "审计日志",
|
||||
Url: "/system/audit_log/list",
|
||||
@@ -180,7 +181,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// 菜单
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "新增",
|
||||
DisplayName: "新增",
|
||||
Url: "/system/menu/add",
|
||||
@@ -200,7 +201,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "新增子菜单",
|
||||
DisplayName: "新增子菜单",
|
||||
Url: "/system/menu/add_children",
|
||||
@@ -220,7 +221,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "编辑",
|
||||
DisplayName: "编辑",
|
||||
Url: "/system/menu/edit",
|
||||
@@ -240,7 +241,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "保存",
|
||||
DisplayName: "保存",
|
||||
Url: "/system/menu/save",
|
||||
@@ -260,7 +261,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "数据",
|
||||
DisplayName: "数据",
|
||||
Url: "/system/menu/data",
|
||||
@@ -280,7 +281,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "刷新",
|
||||
DisplayName: "刷新",
|
||||
Url: "/system/menu/refresh_cache",
|
||||
@@ -301,7 +302,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// 角色
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "新增",
|
||||
DisplayName: "新增",
|
||||
Url: "/system/role/add",
|
||||
@@ -321,7 +322,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "编辑",
|
||||
DisplayName: "编辑",
|
||||
Url: "/system/role/edit",
|
||||
@@ -341,7 +342,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "保存",
|
||||
DisplayName: "保存",
|
||||
Url: "/system/role/save",
|
||||
@@ -361,7 +362,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "数据",
|
||||
DisplayName: "数据",
|
||||
Url: "/system/role/data",
|
||||
@@ -381,7 +382,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "刷新",
|
||||
DisplayName: "刷新",
|
||||
Url: "/system/role/refresh_cache",
|
||||
@@ -401,7 +402,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "重建父路径",
|
||||
DisplayName: "重建父路径",
|
||||
Url: "/system/role/rebuild_parent_path",
|
||||
@@ -421,7 +422,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "权限刷新",
|
||||
DisplayName: "权限刷新",
|
||||
Url: "/system/role/refresh_role_menus",
|
||||
@@ -441,7 +442,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "设置权限",
|
||||
DisplayName: "设置权限",
|
||||
Url: "/system/role/set_menu",
|
||||
@@ -462,7 +463,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// 部门
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "新增",
|
||||
DisplayName: "新增",
|
||||
Url: "/system/department/add",
|
||||
@@ -482,7 +483,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "新增子部门",
|
||||
DisplayName: "新增子部门",
|
||||
Url: "/system/department/add_children",
|
||||
@@ -502,7 +503,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "编辑",
|
||||
DisplayName: "编辑",
|
||||
Url: "/system/department/edit",
|
||||
@@ -522,7 +523,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "保存",
|
||||
DisplayName: "保存",
|
||||
Url: "/system/department/save",
|
||||
@@ -542,7 +543,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "数据",
|
||||
DisplayName: "数据",
|
||||
Url: "/system/department/data",
|
||||
@@ -562,7 +563,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "刷新",
|
||||
DisplayName: "刷新",
|
||||
Url: "/system/department/refresh_cache",
|
||||
@@ -582,7 +583,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "重建父路径",
|
||||
DisplayName: "重建父路径",
|
||||
Url: "/system/department/rebuild_parent_path",
|
||||
@@ -603,7 +604,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// 用户
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "新增",
|
||||
DisplayName: "新增",
|
||||
Url: "/system/user/add",
|
||||
@@ -623,7 +624,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "编辑",
|
||||
DisplayName: "编辑",
|
||||
Url: "/system/user/edit",
|
||||
@@ -643,7 +644,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "基本资料",
|
||||
DisplayName: "基本资料",
|
||||
Url: "/system/user/profile",
|
||||
@@ -663,7 +664,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "保存",
|
||||
DisplayName: "保存",
|
||||
Url: "/system/user/save",
|
||||
@@ -684,7 +685,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// 基础数据
|
||||
basicData, err := r.Create(ctx, &system.Menu{
|
||||
basicData, err := s.Create(ctx, &system.Menu{
|
||||
Name: "基础数据",
|
||||
DisplayName: "基础数据",
|
||||
Url: uuid.Must(uuid.NewRandom()).String(),
|
||||
@@ -705,7 +706,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// 系统配置
|
||||
systemConfig, err := r.Create(ctx, &system.Menu{
|
||||
systemConfig, err := s.Create(ctx, &system.Menu{
|
||||
Name: "系统属性",
|
||||
DisplayName: "系统属性",
|
||||
Url: "/system/config/list",
|
||||
@@ -725,7 +726,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "新增",
|
||||
DisplayName: "新增",
|
||||
Url: "/system/config/add",
|
||||
@@ -745,7 +746,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "编辑",
|
||||
DisplayName: "编辑",
|
||||
Url: "/system/config/edit",
|
||||
@@ -765,7 +766,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "保存",
|
||||
DisplayName: "保存",
|
||||
Url: "/system/config/save",
|
||||
@@ -785,7 +786,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "重置Pear",
|
||||
DisplayName: "重置Pear",
|
||||
Url: "/system/config/reset_pear",
|
||||
@@ -805,7 +806,7 @@ func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Create(ctx, &system.Menu{
|
||||
_, err = s.Create(ctx, &system.Menu{
|
||||
Name: "刷新",
|
||||
DisplayName: "刷新",
|
||||
Url: "/system/config/refresh_cache",
|
||||
@@ -1,148 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"management/internal/erpserver/model/dto"
|
||||
"management/internal/erpserver/model/system"
|
||||
"management/internal/erpserver/repository"
|
||||
"management/internal/pkg/database"
|
||||
)
|
||||
|
||||
type roleRepository struct {
|
||||
repo *repository.Repository
|
||||
}
|
||||
|
||||
func NewRoleRepository(repo *repository.Repository) system.RoleRepository {
|
||||
return &roleRepository{
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *roleRepository) Initialize(ctx context.Context) (*system.Role, error) {
|
||||
var count int64
|
||||
if err := r.repo.DB(ctx).Model(&system.Role{}).Count(&count).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if count == 0 {
|
||||
obj := system.Role{
|
||||
Name: "Company",
|
||||
DisplayName: "公司",
|
||||
Vip: false,
|
||||
ParentID: 0,
|
||||
ParentPath: ",0,",
|
||||
Status: 0,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
if err := r.Create(ctx, &obj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
obj1 := system.Role{
|
||||
Name: "SuperAdmin",
|
||||
DisplayName: "超级管理员",
|
||||
Vip: true,
|
||||
ParentID: obj.ID,
|
||||
ParentPath: fmt.Sprintf(",0,%d,", obj.ID),
|
||||
Status: 0,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
if err := r.Create(ctx, &obj1); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &obj1, nil
|
||||
}
|
||||
|
||||
var role system.Role
|
||||
err := r.repo.DB(ctx).Where("vip = ?", true).First(&role).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &role, nil
|
||||
}
|
||||
|
||||
func (r *roleRepository) Create(ctx context.Context, obj *system.Role) error {
|
||||
return r.repo.DB(ctx).Create(obj).Error
|
||||
}
|
||||
|
||||
func (r *roleRepository) Update(ctx context.Context, obj *system.Role) error {
|
||||
return r.repo.DB(ctx).Save(obj).Error
|
||||
}
|
||||
|
||||
func (r *roleRepository) Get(ctx context.Context, id int32) (*system.Role, error) {
|
||||
var role system.Role
|
||||
err := r.repo.DB(ctx).Where("id = ?", id).First(&role).Error
|
||||
if err != nil {
|
||||
if database.IsNoRows(err) {
|
||||
return nil, fmt.Errorf("role %d not found: %w", id, err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &role, nil
|
||||
}
|
||||
|
||||
func (r *roleRepository) All(ctx context.Context) ([]*system.Role, error) {
|
||||
var roles []*system.Role
|
||||
err := r.repo.DB(ctx).Find(&roles).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
func (r *roleRepository) List(ctx context.Context, q dto.SearchDto) ([]*system.Role, int64, error) {
|
||||
query := r.repo.DB(ctx).
|
||||
Model(&system.Role{}).
|
||||
Where("created_at BETWEEN ? AND ?", q.SearchTimeBegin, q.SearchTimeEnd)
|
||||
if q.SearchID != 0 {
|
||||
query = query.Where("id = ?", q.SearchID)
|
||||
}
|
||||
if q.SearchParentID != 0 && q.SearchParentID != 1 {
|
||||
query = query.Where("parent_id = ?", q.SearchParentID)
|
||||
}
|
||||
if q.SearchName != "" {
|
||||
query = query.Where("name LIKE ?", "%"+q.SearchName+"%")
|
||||
}
|
||||
if q.SearchStatus != 9999 {
|
||||
query = query.Where("status = ?", q.SearchStatus)
|
||||
}
|
||||
|
||||
var count int64
|
||||
err := query.Count(&count).Error
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
var departs []*system.Role
|
||||
err = query.
|
||||
Order("id DESC").
|
||||
Offset((q.Page - 1) * q.Rows).
|
||||
Limit(q.Rows).
|
||||
Find(&departs).Error
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return departs, count, nil
|
||||
}
|
||||
|
||||
func (r *roleRepository) RebuildParentPath(ctx context.Context) error {
|
||||
query := `UPDATE sys_role AS tm
|
||||
SET parent_path = (SELECT ',' || string_agg(cast(t.parent_id AS VARCHAR), ',') || ','
|
||||
FROM (WITH RECURSIVE temp (id, parent_id) AS (SELECT id, tm.parent_id
|
||||
FROM sys_role
|
||||
WHERE id = tm.id
|
||||
UNION ALL
|
||||
SELECT sys_role.id, sys_role.parent_id
|
||||
FROM sys_role,
|
||||
temp
|
||||
WHERE sys_role.id = temp.parent_id)
|
||||
SELECT id, parent_id
|
||||
FROM temp
|
||||
ORDER BY id) AS t)
|
||||
WHERE tm.status = 0;`
|
||||
return r.repo.DB(ctx).Exec(query).Error
|
||||
}
|
||||
48
internal/erpserver/repository/system/role/filter.go
Normal file
48
internal/erpserver/repository/system/role/filter.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package role
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
|
||||
"management/internal/erpserver/model/dto"
|
||||
)
|
||||
|
||||
func applyFilter(filter dto.SearchDto, data map[string]any, buf *bytes.Buffer) {
|
||||
var wc []string
|
||||
|
||||
if filter.SearchTimeBegin != "" && filter.SearchTimeEnd == "" {
|
||||
data["start_at"] = filter.SearchTimeBegin
|
||||
data["end_at"] = filter.SearchTimeEnd
|
||||
wc = append(wc, "created_at BETWEEN :start_at AND :end_at")
|
||||
}
|
||||
|
||||
if filter.SearchEmail != "" {
|
||||
data["email"] = filter.SearchEmail
|
||||
wc = append(wc, "email LIKE :email")
|
||||
}
|
||||
|
||||
if filter.SearchID != 0 {
|
||||
data["id"] = filter.SearchID
|
||||
wc = append(wc, "id = :id")
|
||||
}
|
||||
|
||||
if filter.SearchParentID != 0 && filter.SearchParentID != 1 {
|
||||
data["parent_id"] = filter.SearchParentID
|
||||
wc = append(wc, "parent_id = :parent_id")
|
||||
}
|
||||
|
||||
if filter.SearchName != "" {
|
||||
data["name"] = filter.SearchName
|
||||
wc = append(wc, "name LIKE :name")
|
||||
}
|
||||
|
||||
if filter.SearchStatus != 9999 {
|
||||
data["status"] = filter.SearchStatus
|
||||
wc = append(wc, "status = :status")
|
||||
}
|
||||
|
||||
if len(wc) > 0 {
|
||||
buf.WriteString(" WHERE ")
|
||||
buf.WriteString(strings.Join(wc, " AND "))
|
||||
}
|
||||
}
|
||||
236
internal/erpserver/repository/system/role/role.go
Normal file
236
internal/erpserver/repository/system/role/role.go
Normal file
@@ -0,0 +1,236 @@
|
||||
package role
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"management/internal/erpserver/model/dto"
|
||||
"management/internal/erpserver/model/system"
|
||||
"management/internal/erpserver/repository"
|
||||
"management/internal/pkg/sqldb"
|
||||
|
||||
"github.com/drhin/logger"
|
||||
)
|
||||
|
||||
type store struct {
|
||||
db *repository.Store
|
||||
log *logger.Logger
|
||||
}
|
||||
|
||||
func NewStore(db *repository.Store, log *logger.Logger) system.RoleRepository {
|
||||
return &store{
|
||||
db: db,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *store) Initialize(ctx context.Context) (*system.Role, error) {
|
||||
count, err := s.Count(ctx, dto.SearchDto{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if count == 0 {
|
||||
obj := system.Role{
|
||||
Name: "Company",
|
||||
DisplayName: "公司",
|
||||
Vip: false,
|
||||
ParentID: 0,
|
||||
ParentPath: ",0,",
|
||||
Status: 0,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
if err := s.Create(ctx, &obj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
obj1 := system.Role{
|
||||
Name: "SuperAdmin",
|
||||
DisplayName: "超级管理员",
|
||||
Vip: true,
|
||||
ParentID: obj.ID,
|
||||
ParentPath: fmt.Sprintf(",0,%d,", obj.ID),
|
||||
Status: 0,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
if err := s.Create(ctx, &obj1); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &obj1, nil
|
||||
}
|
||||
|
||||
return s.GetByVip(ctx, true)
|
||||
|
||||
}
|
||||
|
||||
func (s *store) Create(ctx context.Context, obj *system.Role) error {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
INSERT INTO sys_role (
|
||||
name, display_name, parent_id, parent_path, vip, status, sort
|
||||
) VALUES (
|
||||
:name, :display_name, :parent_id, :parent_path, :vip, :status, :sort
|
||||
)`
|
||||
|
||||
return sqldb.NamedExecContext(ctx, s.log, s.db.DB(ctx), q, obj)
|
||||
}
|
||||
|
||||
func (s *store) Update(ctx context.Context, obj *system.Role) error {
|
||||
const q = `
|
||||
UPDATE sys_role
|
||||
SET name = :name,
|
||||
display_name = :display_name,
|
||||
parent_id = :parent_id,
|
||||
parent_path = :parent_path,
|
||||
status = :status,
|
||||
sort = :sort,
|
||||
updated_at = :updated_at
|
||||
WHERE id = :id;`
|
||||
|
||||
return sqldb.NamedExecContext(ctx, s.log, s.db.DB(ctx), q, obj)
|
||||
}
|
||||
|
||||
func (s *store) GetByVip(ctx context.Context, vip bool) (*system.Role, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
id, name, display_name, parent_id, parent_path, vip, status, sort, created_at, updated_at
|
||||
FROM
|
||||
sys_role
|
||||
WHERE
|
||||
vip = :vip;`
|
||||
|
||||
data := map[string]any{
|
||||
"vip": vip,
|
||||
}
|
||||
|
||||
var role system.Role
|
||||
if err := sqldb.NamedQueryStruct(ctx, s.log, s.db.DB(ctx), q, data, &role); err != nil {
|
||||
return nil, fmt.Errorf("select vip role: %w", err)
|
||||
}
|
||||
|
||||
return &role, nil
|
||||
}
|
||||
|
||||
func (s *store) Get(ctx context.Context, id int32) (*system.Role, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
id, name, display_name, parent_id, parent_path, vip, status, sort, created_at, updated_at
|
||||
FROM
|
||||
sys_role
|
||||
WHERE
|
||||
id = :id;`
|
||||
|
||||
data := map[string]any{
|
||||
"id": id,
|
||||
}
|
||||
|
||||
var role system.Role
|
||||
err := sqldb.NamedQueryStruct(ctx, s.log, s.db.DB(ctx), q, data, &role)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("select id role: %w", err)
|
||||
}
|
||||
|
||||
return &role, nil
|
||||
}
|
||||
|
||||
func (s *store) All(ctx context.Context) ([]*system.Role, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
id, name, display_name, parent_id, parent_path, vip, status, sort, created_at, updated_at
|
||||
FROM
|
||||
sys_role;`
|
||||
|
||||
data := map[string]any{}
|
||||
|
||||
var roles []system.Role
|
||||
err := sqldb.NamedQuerySlice(ctx, s.log, s.db.DB(ctx), q, data, &roles)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("select all role: %w", err)
|
||||
}
|
||||
|
||||
return toPointer(roles), nil
|
||||
}
|
||||
|
||||
func (s *store) Count(ctx context.Context, filter dto.SearchDto) (int64, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
COUNT(1)
|
||||
FROM
|
||||
sys_role`
|
||||
|
||||
data := map[string]any{}
|
||||
|
||||
buf := bytes.NewBufferString(q)
|
||||
applyFilter(filter, data, buf)
|
||||
|
||||
var count struct {
|
||||
Count int64 `db:"count"`
|
||||
}
|
||||
|
||||
err := sqldb.NamedQueryStruct(ctx, s.log, s.db.DB(ctx), buf.String(), data, &count)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("select count role: %w", err)
|
||||
}
|
||||
|
||||
return count.Count, nil
|
||||
}
|
||||
|
||||
func (s *store) List(ctx context.Context, filter dto.SearchDto) ([]*system.Role, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
id, name, display_name, parent_id, parent_path, vip, status, sort, created_at, updated_at
|
||||
FROM
|
||||
sys_role`
|
||||
|
||||
data := map[string]any{
|
||||
"offset": (filter.Page - 1) * filter.Rows,
|
||||
"rows_per_page": filter.Rows,
|
||||
}
|
||||
|
||||
buf := bytes.NewBufferString(q)
|
||||
applyFilter(filter, data, buf)
|
||||
|
||||
buf.WriteString(" ORDER BY id DESC")
|
||||
buf.WriteString(" LIMIT :rows_per_page OFFSET :offset")
|
||||
|
||||
var roles []system.Role
|
||||
err := sqldb.NamedQuerySlice(ctx, s.log, s.db.DB(ctx), buf.String(), data, &roles)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return toPointer(roles), nil
|
||||
}
|
||||
|
||||
func (s *store) RebuildParentPath(ctx context.Context) error {
|
||||
query := `UPDATE sys_role AS tm
|
||||
SET parent_path = (SELECT ',' || string_agg(cast(t.parent_id AS VARCHAR), ',') || ','
|
||||
FROM (WITH RECURSIVE temp (id, parent_id) AS (SELECT id, tm.parent_id
|
||||
FROM sys_role
|
||||
WHERE id = tm.id
|
||||
UNION ALL
|
||||
SELECT sys_role.id, sys_role.parent_id
|
||||
FROM sys_role,
|
||||
temp
|
||||
WHERE sys_role.id = temp.parent_id)
|
||||
SELECT id, parent_id
|
||||
FROM temp
|
||||
ORDER BY id) AS t)
|
||||
WHERE tm.status = 0;`
|
||||
return sqldb.NamedExecContext(ctx, s.log, s.db.DB(ctx), query, nil)
|
||||
}
|
||||
|
||||
func toPointer(data []system.Role) []*system.Role {
|
||||
var res []*system.Role
|
||||
for _, v := range data {
|
||||
res = append(res, &v)
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"management/internal/erpserver/model/system"
|
||||
"management/internal/erpserver/repository"
|
||||
)
|
||||
|
||||
type roleMenuRepository struct {
|
||||
repo *repository.Repository
|
||||
}
|
||||
|
||||
func NewRoleMenuRepository(repo *repository.Repository) system.RoleMenuRepository {
|
||||
return &roleMenuRepository{
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *roleMenuRepository) Create(ctx context.Context, obj []*system.RoleMenu) error {
|
||||
return r.repo.DB(ctx).Create(obj).Error
|
||||
}
|
||||
|
||||
func (r *roleMenuRepository) DeleteByRoleID(ctx context.Context, roleID int32) error {
|
||||
return r.repo.DB(ctx).Where("role_id = ?", roleID).Delete(&system.RoleMenu{}).Error
|
||||
}
|
||||
|
||||
func (r *roleMenuRepository) ListByRoleID(ctx context.Context, roleID int32) ([]*system.RoleMenu, error) {
|
||||
var roleMenus []*system.RoleMenu
|
||||
err := r.repo.DB(ctx).Where("role_id = ?", roleID).Find(&roleMenus).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return roleMenus, nil
|
||||
}
|
||||
86
internal/erpserver/repository/system/rolemenu/role_menu.go
Normal file
86
internal/erpserver/repository/system/rolemenu/role_menu.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package rolemenu
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"management/internal/erpserver/model/system"
|
||||
"management/internal/erpserver/repository"
|
||||
"management/internal/pkg/sqldb"
|
||||
|
||||
"github.com/drhin/logger"
|
||||
)
|
||||
|
||||
type store struct {
|
||||
db *repository.Store
|
||||
log *logger.Logger
|
||||
}
|
||||
|
||||
func NewStore(db *repository.Store, log *logger.Logger) system.RoleMenuRepository {
|
||||
return &store{
|
||||
db: db,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *store) Create(ctx context.Context, obj []*system.RoleMenu) error {
|
||||
if len(obj) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
INSERT INTO sys_role_menu (
|
||||
role_id, menu_id
|
||||
) VALUES (
|
||||
:role_id, :menu_id
|
||||
);`
|
||||
|
||||
return sqldb.NamedExecContext(ctx, s.log, s.db.DB(ctx), q, obj)
|
||||
}
|
||||
|
||||
func (s *store) DeleteByRoleID(ctx context.Context, roleID int32) error {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
DELETE FROM
|
||||
sys_role_menu
|
||||
WHERE
|
||||
role_id = :role_id;`
|
||||
|
||||
data := map[string]any{
|
||||
"role_id": roleID,
|
||||
}
|
||||
|
||||
return sqldb.NamedExecContext(ctx, s.log, s.db.DB(ctx), q, data)
|
||||
}
|
||||
|
||||
func (s *store) ListByRoleID(ctx context.Context, roleID int32) ([]*system.RoleMenu, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
role_id, menu_id
|
||||
FROM
|
||||
sys_role_menu
|
||||
WHERE
|
||||
role_id = :role_id;`
|
||||
|
||||
data := map[string]any{
|
||||
"role_id": roleID,
|
||||
}
|
||||
|
||||
var roleMenus []system.RoleMenu
|
||||
err := sqldb.NamedQuerySlice(ctx, s.log, s.db.DB(ctx), q, data, &roleMenus)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("select role menu by role id: %w", err)
|
||||
}
|
||||
|
||||
return toPointer(roleMenus), nil
|
||||
}
|
||||
|
||||
func toPointer(data []system.RoleMenu) []*system.RoleMenu {
|
||||
var res []*system.RoleMenu
|
||||
for _, v := range data {
|
||||
res = append(res, &v)
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"management/internal/erpserver/model/dto"
|
||||
"management/internal/erpserver/model/system"
|
||||
"management/internal/erpserver/repository"
|
||||
"management/internal/pkg/crypto"
|
||||
"management/internal/pkg/database"
|
||||
"management/internal/pkg/rand"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type userRepository struct {
|
||||
repo *repository.Repository
|
||||
}
|
||||
|
||||
func NewUserRepository(repo *repository.Repository) system.UserRepository {
|
||||
return &userRepository{
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *userRepository) Initialize(ctx context.Context, departId, roleId int32) error {
|
||||
var count int64
|
||||
if err := s.repo.DB(ctx).Model(&system.User{}).Count(&count).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if count == 0 {
|
||||
salt, err := rand.String(10)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
password := "secret"
|
||||
hashedPassword, err := crypto.BcryptHashPassword(password + salt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
initTime, err := time.ParseInLocation(time.DateTime, "0001-01-01 00:00:00", time.Local)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user := system.User{
|
||||
Uuid: uuid.Must(uuid.NewV7()),
|
||||
Email: "1185230223@qq.com",
|
||||
Username: "kenneth",
|
||||
HashedPassword: hashedPassword,
|
||||
Salt: salt,
|
||||
Avatar: "/assets/admin/images/avatar.jpg",
|
||||
Gender: 1,
|
||||
DepartmentID: departId,
|
||||
RoleID: roleId,
|
||||
Status: 0,
|
||||
ChangePasswordAt: initTime,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
return s.Create(ctx, &user)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *userRepository) Create(ctx context.Context, obj *system.User) error {
|
||||
return s.repo.DB(ctx).Create(obj).Error
|
||||
}
|
||||
|
||||
func (s *userRepository) Update(ctx context.Context, obj *system.User) error {
|
||||
return s.repo.DB(ctx).Save(obj).Error
|
||||
}
|
||||
|
||||
func (s *userRepository) Get(ctx context.Context, id int32) (*system.User, error) {
|
||||
var user system.User
|
||||
err := s.repo.DB(ctx).Where("id = ?", id).First(&user).Error
|
||||
if err != nil {
|
||||
if database.IsNoRows(err) {
|
||||
return nil, fmt.Errorf("user %d not found: %w", id, err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
func (s *userRepository) GetByEmail(ctx context.Context, email string) (*system.User, error) {
|
||||
var user system.User
|
||||
err := s.repo.DB(ctx).Where("email = ?", email).First(&user).Error
|
||||
if err != nil {
|
||||
if database.IsNoRows(err) {
|
||||
return nil, fmt.Errorf("user by email %s not found: %w", email, err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
func (s *userRepository) All(ctx context.Context) ([]*system.User, error) {
|
||||
var users []*system.User
|
||||
err := s.repo.DB(ctx).Find(&users).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func (s *userRepository) List(ctx context.Context, q dto.SearchDto) ([]*system.User, int64, error) {
|
||||
query := s.repo.DB(ctx).
|
||||
Model(&system.User{}).
|
||||
Preload("Role").
|
||||
Preload("Department").
|
||||
Where("created_at BETWEEN ? AND ?", q.SearchTimeBegin, q.SearchTimeEnd)
|
||||
if q.SearchID != 0 {
|
||||
query = query.Where("id = ?", q.SearchID)
|
||||
}
|
||||
if q.SearchName != "" {
|
||||
query = query.Where("username LIKE ?", "%"+q.SearchName+"%")
|
||||
}
|
||||
if q.SearchEmail != "" {
|
||||
query = query.Where("email LIKE ?", "%"+q.SearchEmail+"%")
|
||||
}
|
||||
if q.SearchStatus != 9999 {
|
||||
query = query.Where("status = ?", q.SearchStatus)
|
||||
}
|
||||
|
||||
var count int64
|
||||
err := query.Count(&count).Error
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
var users []*system.User
|
||||
err = query.
|
||||
Order("id DESC").
|
||||
Offset((q.Page - 1) * q.Rows).
|
||||
Limit(q.Rows).
|
||||
Find(&users).Error
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return users, count, nil
|
||||
}
|
||||
43
internal/erpserver/repository/system/user/filter.go
Normal file
43
internal/erpserver/repository/system/user/filter.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
|
||||
"management/internal/erpserver/model/dto"
|
||||
)
|
||||
|
||||
func applyFilter(filter dto.SearchDto, data map[string]any, buf *bytes.Buffer) {
|
||||
var wc []string
|
||||
|
||||
if filter.SearchTimeBegin != "" && filter.SearchTimeEnd == "" {
|
||||
data["start_at"] = filter.SearchTimeBegin
|
||||
data["end_at"] = filter.SearchTimeEnd
|
||||
wc = append(wc, "created_at BETWEEN :start_at AND :end_at")
|
||||
}
|
||||
|
||||
if filter.SearchID != 0 {
|
||||
data["id"] = filter.SearchID
|
||||
wc = append(wc, "id = :id")
|
||||
}
|
||||
|
||||
if filter.SearchName != "" {
|
||||
data["username"] = filter.SearchName
|
||||
wc = append(wc, "username LIKE :username")
|
||||
}
|
||||
|
||||
if filter.SearchEmail != "" {
|
||||
data["email"] = filter.SearchEmail
|
||||
wc = append(wc, "email LIKE :email")
|
||||
}
|
||||
|
||||
if filter.SearchStatus != 9999 {
|
||||
data["status"] = filter.SearchStatus
|
||||
wc = append(wc, "status = :status")
|
||||
}
|
||||
|
||||
if len(wc) > 0 {
|
||||
buf.WriteString(" WHERE ")
|
||||
buf.WriteString(strings.Join(wc, " AND "))
|
||||
}
|
||||
}
|
||||
234
internal/erpserver/repository/system/user/user.go
Normal file
234
internal/erpserver/repository/system/user/user.go
Normal file
@@ -0,0 +1,234 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"management/internal/erpserver/model/dto"
|
||||
"management/internal/erpserver/model/system"
|
||||
"management/internal/erpserver/repository"
|
||||
"management/internal/pkg/crypto"
|
||||
"management/internal/pkg/rand"
|
||||
"management/internal/pkg/sqldb"
|
||||
|
||||
"github.com/drhin/logger"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type store struct {
|
||||
db *repository.Store
|
||||
log *logger.Logger
|
||||
}
|
||||
|
||||
func NewStore(db *repository.Store, log *logger.Logger) system.UserRepository {
|
||||
return &store{
|
||||
db: db,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *store) Initialize(ctx context.Context, departId, roleId int32) error {
|
||||
count, err := s.Count(ctx, dto.SearchDto{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if count == 0 {
|
||||
salt, err := rand.String(10)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
password := "secret"
|
||||
hashedPassword, err := crypto.BcryptHashPassword(password + salt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
initTime, err := time.ParseInLocation(time.DateTime, "0001-01-01 00:00:00", time.Local)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user := system.User{
|
||||
Uuid: uuid.Must(uuid.NewV7()),
|
||||
Email: "1185230223@qq.com",
|
||||
Username: "kenneth",
|
||||
HashedPassword: hashedPassword,
|
||||
Salt: salt,
|
||||
Avatar: "/assets/admin/images/avatar.jpg",
|
||||
Gender: 1,
|
||||
DepartmentID: departId,
|
||||
RoleID: roleId,
|
||||
Status: 0,
|
||||
ChangePasswordAt: initTime,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
return s.Create(ctx, &user)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *store) Create(ctx context.Context, obj *system.User) error {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
INSERT INTO sys_user (
|
||||
uuid, email, username, hashed_password, salt, avatar, gender, department_id, role_id, status
|
||||
) VALUES (
|
||||
:uuid, :email, :username, :hashed_password, :salt, :avatar, :gender, :department_id, :role_id, :status
|
||||
);`
|
||||
|
||||
return sqldb.NamedExecContext(ctx, s.log, s.db.DB(ctx), q, obj)
|
||||
}
|
||||
|
||||
func (s *store) Update(ctx context.Context, obj *system.User) error {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
UPDATE sys_user
|
||||
SET email = :email,
|
||||
username = :username,
|
||||
hashed_password = :hashed_password,
|
||||
avatar = :avatar,
|
||||
gender = :gender,
|
||||
department_id = :department_id,
|
||||
role_id = :role_id,
|
||||
status = :status,
|
||||
change_password_at = :change_password_at,
|
||||
updated_at = :updated_at
|
||||
WHERE id = :id;`
|
||||
|
||||
return sqldb.NamedExecContext(ctx, s.log, s.db.DB(ctx), q, obj)
|
||||
}
|
||||
|
||||
func (s *store) Get(ctx context.Context, id int32) (*system.User, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
id, uuid, email, username, hashed_password, salt, avatar, gender, department_id,
|
||||
role_id, status, change_password_at, created_at, updated_at
|
||||
FROM
|
||||
sys_user
|
||||
WHERE
|
||||
id = :id;`
|
||||
|
||||
data := map[string]any{
|
||||
"id": id,
|
||||
}
|
||||
|
||||
var user system.User
|
||||
err := sqldb.NamedQueryStruct(ctx, s.log, s.db.DB(ctx), q, data, &user)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("select id user: %w", err)
|
||||
}
|
||||
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
func (s *store) GetByEmail(ctx context.Context, email string) (*system.User, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
id, uuid, email, username, hashed_password, salt, avatar, gender, department_id,
|
||||
role_id, status, change_password_at, created_at, updated_at
|
||||
FROM
|
||||
sys_user
|
||||
WHERE
|
||||
email = :email;`
|
||||
|
||||
data := map[string]any{
|
||||
"email": email,
|
||||
}
|
||||
|
||||
var user system.User
|
||||
err := sqldb.NamedQueryStruct(ctx, s.log, s.db.DB(ctx), q, data, &user)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("select email user: %w", err)
|
||||
}
|
||||
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
func (s *store) All(ctx context.Context) ([]*system.User, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
id, uuid, email, username, hashed_password, salt, avatar, gender, department_id,
|
||||
role_id, status, change_password_at, created_at, updated_at
|
||||
FROM
|
||||
sys_user;`
|
||||
|
||||
data := map[string]any{}
|
||||
|
||||
var users []system.User
|
||||
err := sqldb.NamedQuerySlice(ctx, s.log, s.db.DB(ctx), q, data, &users)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("select all role: %w", err)
|
||||
}
|
||||
|
||||
return toPointer(users), nil
|
||||
}
|
||||
|
||||
func (s *store) Count(ctx context.Context, filter dto.SearchDto) (int64, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
COUNT(1)
|
||||
FROM
|
||||
sys_user`
|
||||
|
||||
data := map[string]any{}
|
||||
|
||||
buf := bytes.NewBufferString(q)
|
||||
applyFilter(filter, data, buf)
|
||||
|
||||
var count struct {
|
||||
Count int64 `db:"count"`
|
||||
}
|
||||
|
||||
err := sqldb.NamedQueryStruct(ctx, s.log, s.db.DB(ctx), buf.String(), data, &count)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("select count user: %w", err)
|
||||
}
|
||||
|
||||
return count.Count, nil
|
||||
}
|
||||
|
||||
func (s *store) List(ctx context.Context, filter dto.SearchDto) ([]*system.User, error) {
|
||||
//goland:noinspection ALL
|
||||
const q = `
|
||||
SELECT
|
||||
id, uuid, email, username, hashed_password, salt, avatar, gender, department_id,
|
||||
role_id, status, change_password_at, created_at, updated_at
|
||||
FROM
|
||||
sys_user`
|
||||
|
||||
data := map[string]any{
|
||||
"offset": (filter.Page - 1) * filter.Rows,
|
||||
"rows_per_page": filter.Rows,
|
||||
}
|
||||
|
||||
buf := bytes.NewBufferString(q)
|
||||
applyFilter(filter, data, buf)
|
||||
|
||||
buf.WriteString(" ORDER BY id DESC")
|
||||
buf.WriteString(" LIMIT :rows_per_page OFFSET :offset")
|
||||
|
||||
var users []system.User
|
||||
err := sqldb.NamedQuerySlice(ctx, s.log, s.db.DB(ctx), buf.String(), data, &users)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return toPointer(users), nil
|
||||
}
|
||||
|
||||
func toPointer(data []system.User) []*system.User {
|
||||
var res []*system.User
|
||||
for _, v := range data {
|
||||
res = append(res, &v)
|
||||
}
|
||||
return res
|
||||
}
|
||||
Reference in New Issue
Block a user