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(), } _, err = s.Create(ctx, &user) return err } return nil } func (s *store) Create(ctx context.Context, obj *system.User) (*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 ) RETURNING *;` data := map[string]any{ "uuid": obj.Uuid.String(), "email": obj.Email, "username": obj.Username, "hashed_password": obj.HashedPassword, "salt": obj.Salt, "avatar": obj.Avatar, "gender": obj.Gender, "department_id": obj.DepartmentID, "role_id": obj.RoleID, "status": obj.Status, } err := sqldb.NamedQueryStruct(ctx, s.log, s.db.DB(ctx), q, data, &obj) if err != nil { return nil, err } return obj, nil } func (s *store) Update(ctx context.Context, obj *system.User) (*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 RETURNING *;` data := map[string]any{ "email": obj.Email, "username": obj.Username, "hashed_password": obj.HashedPassword, "avatar": obj.Avatar, "gender": obj.Gender, "department_id": obj.DepartmentID, "role_id": obj.RoleID, "status": obj.Status, "change_password_at": obj.ChangePasswordAt, "updated_at": obj.UpdatedAt, "id": obj.ID, } err := sqldb.NamedQueryStruct(ctx, s.log, s.db.DB(ctx), q, data, &obj) if err != nil { return nil, err } return obj, nil } 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 }