This commit is contained in:
2026-02-11 17:46:22 +03:00
commit eacfacb13b
266 changed files with 51337 additions and 0 deletions

View File

@@ -0,0 +1,352 @@
package repository
import (
"bssapp-backend/models"
"database/sql"
"errors"
"strings"
"time"
"github.com/lib/pq"
)
var ErrMkUserNotFound = errors.New("mk_user not found")
type MkUserRepository struct {
DB *sql.DB
}
func NewMkUserRepository(db *sql.DB) *MkUserRepository {
return &MkUserRepository{DB: db}
}
// -------------------------------------------------------
// 🔍 GET BY USERNAME
// -------------------------------------------------------
func (r *MkUserRepository) GetByUsername(username string) (*models.MkUser, error) {
username = strings.TrimSpace(username)
var u models.MkUser
err := r.DB.QueryRow(`SELECT
u.id,
u.username,
COALESCE(u.email,'') AS email,
u.is_active,
COALESCE(u.password_hash,'') AS password_hash,
u.force_password_change,
COALESCE(r.id, 0) AS role_id,
COALESCE(r.code, '') AS role_code,
-- ✅ DEPARTMENTS
COALESCE(
array_agg(DISTINCT d.code)
FILTER (WHERE d.code IS NOT NULL),
'{}'
) AS department_codes,
u.password_updated_at,
u.created_at,
u.updated_at,
u.last_login_at
FROM mk_dfusr u
LEFT JOIN dfrole_usr ru
ON ru.dfusr_id = u.id
LEFT JOIN dfrole r
ON r.id = ru.dfrole_id
-- ✅ USER → DEPT
LEFT JOIN dfusr_dprt ud
ON ud.dfusr_id = u.id
AND ud.is_active = true
LEFT JOIN mk_dprt d
ON d.id = ud.dprt_id
WHERE LOWER(u.username) = LOWER($1)
GROUP BY
u.id, r.id
LIMIT 1
`, username).Scan(
&u.ID,
&u.Username,
&u.Email,
&u.IsActive,
&u.PasswordHash,
&u.ForcePasswordChange,
&u.RoleID,
&u.RoleCode,
pq.Array(&u.DepartmentCodes), // ✅
&u.PasswordUpdatedAt,
&u.CreatedAt,
&u.UpdatedAt,
&u.LastLoginAt,
)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, ErrMkUserNotFound
}
return nil, err
}
return &u, nil
}
// -------------------------------------------------------
// 🔍 GET BY ID
// -------------------------------------------------------
func (r *MkUserRepository) GetByID(id int64) (*models.MkUser, error) {
var u models.MkUser
err := r.DB.QueryRow(`
SELECT
u.id,
u.username,
COALESCE(u.email,'') AS email,
u.is_active,
COALESCE(u.password_hash,'') AS password_hash,
u.force_password_change,
COALESCE(r.id, 0) AS role_id,
COALESCE(r.code, '') AS role_code,
-- ✅ DEPARTMENTS
COALESCE(
array_agg(DISTINCT d.code)
FILTER (WHERE d.code IS NOT NULL),
'{}'
) AS department_codes,
u.password_updated_at,
u.created_at,
u.updated_at,
u.last_login_at
FROM mk_dfusr u
LEFT JOIN dfrole_usr ru
ON ru.dfusr_id = u.id
LEFT JOIN dfrole r
ON r.id = ru.dfrole_id
-- ✅ USER → DEPT
LEFT JOIN dfusr_dprt ud
ON ud.dfusr_id = u.id
AND ud.is_active = true
LEFT JOIN mk_dprt d
ON d.id = ud.dprt_id
WHERE LOWER(u.username) = LOWER($1)
GROUP BY
u.id, r.id
LIMIT 1
`, id).Scan(
&u.ID,
&u.Username,
&u.Email,
&u.IsActive,
&u.PasswordHash,
&u.ForcePasswordChange,
&u.RoleID,
&u.RoleCode,
pq.Array(&u.DepartmentCodes), // ✅
&u.PasswordUpdatedAt,
&u.CreatedAt,
&u.UpdatedAt,
&u.LastLoginAt,
)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, ErrMkUserNotFound
}
return nil, err
}
return &u, nil
}
// -------------------------------------------------------
// 🔁 CREATE FROM LEGACY (dfusr → mk_dfusr)
// - id = dfusr.id ✅
// - role / v3 YOK
// -------------------------------------------------------
// -------------------------------------------------------
// 🔁 CREATE FROM LEGACY (dfusr → mk_dfusr) FULL MIGRATION
// -------------------------------------------------------
func (r *MkUserRepository) CreateFromLegacy(
legacy *models.User,
passwordHash string,
) (*models.MkUser, error) {
var u models.MkUser
err := r.DB.QueryRow(`
INSERT INTO mk_dfusr (
id,
username,
email,
full_name,
mobile,
address,
is_active,
password_hash,
force_password_change,
created_at,
updated_at
)
VALUES (
$1,$2,$3,$4,$5,$6,$7,$8,true,now(),now()
)
ON CONFLICT (id)
DO UPDATE SET
email = EXCLUDED.email,
full_name = EXCLUDED.full_name,
mobile = EXCLUDED.mobile,
address = EXCLUDED.address,
password_hash = EXCLUDED.password_hash,
force_password_change= true,
updated_at = now()
RETURNING
id,
username,
COALESCE(email,''),
is_active,
COALESCE(password_hash,''),
force_password_change,
password_updated_at,
created_at,
updated_at,
last_login_at
`,
legacy.ID,
legacy.Username,
legacy.Email,
legacy.FullName,
legacy.Mobile,
legacy.Address,
legacy.IsActive,
passwordHash,
).Scan(
&u.ID,
&u.Username,
&u.Email,
&u.IsActive,
&u.PasswordHash,
&u.ForcePasswordChange,
&u.PasswordUpdatedAt,
&u.CreatedAt,
&u.UpdatedAt,
&u.LastLoginAt,
)
if err != nil {
return nil, err
}
return &u, nil
}
// -------------------------------------------------------
// CREATE NEW USER (NON-LEGACY)
// - id = sequence (>=1000)
// -------------------------------------------------------
func (r *MkUserRepository) CreateNewUser(
username string,
email string,
isActive bool,
) (*models.MkUser, error) {
var u models.MkUser
err := r.DB.QueryRow(`
INSERT INTO mk_dfusr (
username,
email,
is_active,
force_password_change,
created_at,
updated_at
)
VALUES (
$1,$2,$3,true,now(),now()
)
RETURNING
id,
username,
COALESCE(email,'') AS email,
is_active,
COALESCE(password_hash,'') AS password_hash,
force_password_change,
password_updated_at,
created_at,
updated_at,
last_login_at
`,
strings.TrimSpace(username),
strings.TrimSpace(email),
isActive,
).Scan(
&u.ID,
&u.Username,
&u.Email,
&u.IsActive,
&u.PasswordHash,
&u.ForcePasswordChange,
&u.PasswordUpdatedAt,
&u.CreatedAt,
&u.UpdatedAt,
&u.LastLoginAt,
)
if err != nil {
return nil, err
}
return &u, nil
}
// -------------------------------------------------------
// 🕒 TOUCH LAST LOGIN
// -------------------------------------------------------
func (r *MkUserRepository) TouchLastLogin(userID int64) error {
_, err := r.DB.Exec(`
UPDATE mk_dfusr
SET last_login_at = $1,
updated_at = $1
WHERE id = $2
`, time.Now(), userID)
return err
}
// -------------------------------------------------------
// 🔐 UPDATE PASSWORD
// -------------------------------------------------------
func (r *MkUserRepository) UpdatePassword(userID int64, newHash string) error {
_, err := r.DB.Exec(`
UPDATE mk_dfusr
SET
password_hash = $1,
force_password_change = false,
password_updated_at = NOW(),
updated_at = NOW()
WHERE id = $2
`, newHash, userID)
return err
}