162 lines
6.0 KiB
Go
162 lines
6.0 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
)
|
|
|
|
type MemberOverview struct {
|
|
TenantID int64 `db:"tenant_id"`
|
|
MemberID int64 `db:"member_id"`
|
|
MemberNo string `db:"member_no"`
|
|
Username string `db:"username"`
|
|
Mobile string `db:"mobile"`
|
|
InviteCode string `db:"invite_code"`
|
|
MemberStatus int `db:"member_status"`
|
|
MemberCategory int `db:"member_category"`
|
|
CreditScore int `db:"credit_score"`
|
|
AvatarAttachmentID int64 `db:"avatar_attachment_id"`
|
|
AvatarURL string `db:"avatar_url"`
|
|
LevelID int64 `db:"level_id"`
|
|
LevelCode string `db:"level_code"`
|
|
LevelName string `db:"level_name"`
|
|
LevelIconURL string `db:"level_icon_url"`
|
|
CommissionRate int `db:"commission_rate"`
|
|
AvailableAmount int64 `db:"available_amount"`
|
|
FrozenAmount int64 `db:"frozen_amount"`
|
|
TotalIncome int64 `db:"total_income"`
|
|
TotalExpense int64 `db:"total_expense"`
|
|
Currency string `db:"currency"`
|
|
WalletStatus int `db:"wallet_status"`
|
|
WalletVersion int `db:"wallet_version"`
|
|
}
|
|
|
|
type AccountSecurity struct {
|
|
PasswordHash string `db:"password_hash"`
|
|
TradePasswordHash string `db:"trade_password_hash"`
|
|
MemberStatus int `db:"member_status"`
|
|
}
|
|
|
|
type Avatar struct {
|
|
AttachmentID int64 `db:"attachment_id"`
|
|
URL string `db:"url"`
|
|
}
|
|
|
|
func (s *Store) MemberOverview(ctx context.Context, tenantID, memberID int64) (*MemberOverview, error) {
|
|
if s == nil || s.db == nil {
|
|
return nil, errors.New("store is unavailable")
|
|
}
|
|
var row MemberOverview
|
|
err := s.db.GetContext(ctx, &row, `SELECT m.tenant_id,m.id AS member_id,m.member_no,m.username,m.mobile,
|
|
m.invite_code,m.member_status,m.risk_status AS member_category,m.credit_score,
|
|
COALESCE(p.avatar_attachment_id,0) AS avatar_attachment_id,COALESCE(a.file_url,'') AS avatar_url,
|
|
COALESCE(l.id,0) AS level_id,COALESCE(l.level_code,'') AS level_code,
|
|
COALESCE(l.name,'') AS level_name,COALESCE(l.icon_url,'') AS level_icon_url,
|
|
COALESCE(lv.commission_rate,0) AS commission_rate,
|
|
COALESCE(w.available_amount,0) AS available_amount,COALESCE(w.frozen_amount,0) AS frozen_amount,
|
|
COALESCE(w.total_income,0) AS total_income,COALESCE(w.total_expense,0) AS total_expense,
|
|
COALESCE(w.currency,'CNY') AS currency,COALESCE(w.account_status,1) AS wallet_status,
|
|
COALESCE(w.version,0) AS wallet_version
|
|
FROM hg_app_member m
|
|
LEFT JOIN hg_app_member_profile p ON p.tenant_id=m.tenant_id AND p.member_id=m.id
|
|
LEFT JOIN hg_sys_attachment a ON a.id=p.avatar_attachment_id AND a.status=1
|
|
LEFT JOIN hg_app_member_level l ON l.tenant_id=m.tenant_id AND l.id=m.level_id AND l.deleted_at IS NULL
|
|
LEFT JOIN hg_app_member_level_version lv ON lv.tenant_id=l.tenant_id AND lv.id=l.current_version_id
|
|
LEFT JOIN hg_wallet_account w ON w.tenant_id=m.tenant_id AND w.member_id=m.id AND w.currency='CNY'
|
|
WHERE m.tenant_id=? AND m.id=? AND m.member_status=1 AND m.deleted_at IS NULL LIMIT 1`, tenantID, memberID)
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
return nil, ErrAccountNotFound
|
|
}
|
|
return &row, err
|
|
}
|
|
|
|
func (s *Store) UpdateAvatar(ctx context.Context, tenantID, memberID, attachmentID int64) (*Avatar, error) {
|
|
if s == nil || s.db == nil {
|
|
return nil, errors.New("store is unavailable")
|
|
}
|
|
tx, err := s.db.BeginTxx(ctx, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer tx.Rollback()
|
|
var activeMemberID int64
|
|
err = tx.GetContext(ctx, &activeMemberID, `SELECT id FROM hg_app_member
|
|
WHERE tenant_id=? AND id=? AND member_status=1 AND deleted_at IS NULL LIMIT 1 FOR UPDATE`, tenantID, memberID)
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
return nil, ErrAccountNotFound
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var avatar Avatar
|
|
err = tx.GetContext(ctx, &avatar, `SELECT id AS attachment_id,COALESCE(file_url,'') AS url FROM hg_sys_attachment
|
|
WHERE id=? AND app_id='workbench' AND member_id=? AND status=1
|
|
AND mime_type LIKE 'image/%' LIMIT 1 FOR UPDATE`, attachmentID, memberID)
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
return nil, ErrAttachmentInvalid
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
_, err = tx.ExecContext(ctx, `INSERT INTO hg_app_member_profile
|
|
(tenant_id,member_id,avatar_attachment_id,created_by,updated_by)
|
|
VALUES(?,?,?,0,0) ON DUPLICATE KEY UPDATE avatar_attachment_id=VALUES(avatar_attachment_id),updated_at=CURRENT_TIMESTAMP(3)`,
|
|
tenantID, memberID, attachmentID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := tx.Commit(); err != nil {
|
|
return nil, err
|
|
}
|
|
return &avatar, nil
|
|
}
|
|
|
|
func (s *Store) AccountSecurity(ctx context.Context, tenantID, memberID int64) (*AccountSecurity, error) {
|
|
if s == nil || s.db == nil {
|
|
return nil, errors.New("store is unavailable")
|
|
}
|
|
var row AccountSecurity
|
|
err := s.db.GetContext(ctx, &row, `SELECT password_hash,trade_password_hash,member_status
|
|
FROM hg_app_member WHERE tenant_id=? AND id=? AND member_status=1 AND deleted_at IS NULL LIMIT 1`, tenantID, memberID)
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
return nil, ErrAccountNotFound
|
|
}
|
|
return &row, err
|
|
}
|
|
|
|
func (s *Store) UpdateLoginPassword(ctx context.Context, tenantID, memberID int64, oldHash, newHash string) error {
|
|
result, err := s.db.ExecContext(ctx, `UPDATE hg_app_member SET password_hash=?,updated_at=CURRENT_TIMESTAMP(3)
|
|
WHERE tenant_id=? AND id=? AND password_hash=? AND member_status=1 AND deleted_at IS NULL`,
|
|
newHash, tenantID, memberID, oldHash)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
affected, err := result.RowsAffected()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if affected != 1 {
|
|
return ErrConcurrentUpdate
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Store) UpdateTradePassword(ctx context.Context, tenantID, memberID int64, oldHash, newHash string) error {
|
|
result, err := s.db.ExecContext(ctx, `UPDATE hg_app_member SET trade_password_hash=?,updated_at=CURRENT_TIMESTAMP(3)
|
|
WHERE tenant_id=? AND id=? AND trade_password_hash=? AND member_status=1 AND deleted_at IS NULL`,
|
|
newHash, tenantID, memberID, oldHash)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
affected, err := result.RowsAffected()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if affected != 1 {
|
|
return ErrConcurrentUpdate
|
|
}
|
|
return nil
|
|
}
|