89 lines
3.3 KiB
Go
89 lines
3.3 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
)
|
|
|
|
type MemberIMIdentity struct {
|
|
ID int64 `db:"id"`
|
|
TenantID int64 `db:"tenant_id"`
|
|
MemberID int64 `db:"member_id"`
|
|
IMTenantCode string `db:"im_tenant_code"`
|
|
IMUserID string `db:"im_user_id"`
|
|
IMUsername string `db:"im_username"`
|
|
IMPasswordCipher string `db:"im_password_cipher"`
|
|
}
|
|
|
|
type MemberIMProfile struct {
|
|
MemberID int64 `db:"member_id"`
|
|
Username string `db:"username"`
|
|
MemberNo string `db:"member_no"`
|
|
}
|
|
|
|
func (s *Store) CustomerServiceByID(ctx context.Context, tenantID, serviceID int64) (*CustomerService, error) {
|
|
if s == nil || s.db == nil {
|
|
return nil, errors.New("store is unavailable")
|
|
}
|
|
var row CustomerService
|
|
err := s.db.GetContext(ctx, &row, `SELECT id,service_code,name,avatar_url,work_time,online_status,
|
|
service_url,backup_contact,im_tenant_code,COALESCE(im_user_id,'') AS im_user_id,
|
|
COALESCE(im_username,'') AS im_username FROM hg_customer_service
|
|
WHERE tenant_id=? AND id=? AND status=1 AND deleted_at IS NULL LIMIT 1`, tenantID, serviceID)
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
return nil, ErrResourceNotFound
|
|
}
|
|
return &row, err
|
|
}
|
|
|
|
func (s *Store) MemberIMIdentity(ctx context.Context, tenantID, memberID int64) (*MemberIMIdentity, error) {
|
|
if s == nil || s.db == nil {
|
|
return nil, errors.New("store is unavailable")
|
|
}
|
|
var row MemberIMIdentity
|
|
err := s.db.GetContext(ctx, &row, `SELECT id,tenant_id,member_id,im_tenant_code,im_user_id,im_username,im_password_cipher
|
|
FROM hg_app_member_im_identity WHERE tenant_id=? AND member_id=? LIMIT 1`, tenantID, memberID)
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
return nil, ErrResourceNotFound
|
|
}
|
|
return &row, err
|
|
}
|
|
|
|
func (s *Store) MemberIMProfile(ctx context.Context, tenantID, memberID int64) (*MemberIMProfile, error) {
|
|
if s == nil || s.db == nil {
|
|
return nil, errors.New("store is unavailable")
|
|
}
|
|
var row MemberIMProfile
|
|
err := s.db.GetContext(ctx, &row, `SELECT id AS member_id,username,member_no 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) SaveMemberIMIdentity(ctx context.Context, identity *MemberIMIdentity) (*MemberIMIdentity, error) {
|
|
if s == nil || s.db == nil {
|
|
return nil, errors.New("store is unavailable")
|
|
}
|
|
if identity == nil {
|
|
return nil, errors.New("identity is required")
|
|
}
|
|
_, err := s.db.ExecContext(ctx, `INSERT INTO hg_app_member_im_identity
|
|
(tenant_id,member_id,im_tenant_code,im_user_id,im_username,im_password_cipher,sync_status,last_error,created_at,updated_at)
|
|
VALUES(?,?,?,?,?,?,1,'',UTC_TIMESTAMP(3),UTC_TIMESTAMP(3))
|
|
ON DUPLICATE KEY UPDATE im_user_id=VALUES(im_user_id),im_username=VALUES(im_username),
|
|
im_password_cipher=VALUES(im_password_cipher),sync_status=1,last_error='',updated_at=UTC_TIMESTAMP(3)`,
|
|
identity.TenantID, identity.MemberID, identity.IMTenantCode, identity.IMUserID, identity.IMUsername, identity.IMPasswordCipher)
|
|
if err == nil {
|
|
return s.MemberIMIdentity(ctx, identity.TenantID, identity.MemberID)
|
|
}
|
|
// A concurrent request may have completed the same deterministic mapping.
|
|
existing, findErr := s.MemberIMIdentity(ctx, identity.TenantID, identity.MemberID)
|
|
if findErr == nil {
|
|
return existing, nil
|
|
}
|
|
return nil, err
|
|
}
|