feat: 增加客户端采购员归属管理 (#54)
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"cmautobuy/admin/model"
|
||||
@@ -118,12 +119,33 @@ func TouchClient(db *sql.DB, clientID string) error {
|
||||
// Status 是**算出来的**,数据库里没有这个字段。
|
||||
type ClientView struct {
|
||||
model.Client
|
||||
Status string
|
||||
Status string
|
||||
AssignedUserID string
|
||||
AssignedUsername string
|
||||
}
|
||||
|
||||
// ListClientViews 查客户端列表,并把在线状态算出来。
|
||||
func ListClientViews(db *sql.DB, keyword string, threshold time.Duration) ([]ClientView, error) {
|
||||
clients, err := repository.ListClients(db, keyword)
|
||||
return listClientViews(db, keyword, "", threshold)
|
||||
}
|
||||
|
||||
// ListClientViewsForUser 按网页登录身份限制可见范围:管理员全量,采购员只看自己。
|
||||
func ListClientViewsForUser(db *sql.DB, actor *model.User, keyword string, threshold time.Duration) ([]ClientView, error) {
|
||||
if actor == nil {
|
||||
return nil, ErrUnauthenticated
|
||||
}
|
||||
visibleUserID := ""
|
||||
if !actor.IsAdmin() {
|
||||
if actor.Role != model.RolePurchaser {
|
||||
return nil, ErrAdminRequired
|
||||
}
|
||||
visibleUserID = actor.UserID
|
||||
}
|
||||
return listClientViews(db, keyword, visibleUserID, threshold)
|
||||
}
|
||||
|
||||
func listClientViews(db *sql.DB, keyword, visibleUserID string, threshold time.Duration) ([]ClientView, error) {
|
||||
clients, err := repository.ListClientsForUser(db, keyword, visibleUserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -132,13 +154,62 @@ func ListClientViews(db *sql.DB, keyword string, threshold time.Duration) ([]Cli
|
||||
views := make([]ClientView, 0, len(clients))
|
||||
for _, c := range clients {
|
||||
views = append(views, ClientView{
|
||||
Client: c,
|
||||
Status: c.StatusText(now, threshold),
|
||||
Client: c.Client,
|
||||
Status: c.StatusText(now, threshold),
|
||||
AssignedUserID: c.AssignedUserID,
|
||||
AssignedUsername: c.AssignedUsername,
|
||||
})
|
||||
}
|
||||
return views, nil
|
||||
}
|
||||
|
||||
// ListAssignableClients 返回当前用户在采购任务页面可选择的客户端。
|
||||
// 当前创建页面尚未实现,本函数固定未来入口也必须沿用相同权限边界。
|
||||
func ListAssignableClients(db *sql.DB, actor *model.User, threshold time.Duration) ([]ClientView, error) {
|
||||
return ListClientViewsForUser(db, actor, "", threshold)
|
||||
}
|
||||
|
||||
// ListActivePurchasers 返回管理员可选择的绑定目标。
|
||||
func ListActivePurchasers(db *sql.DB, actor *model.User) ([]model.User, error) {
|
||||
if actor == nil || !actor.IsAdmin() {
|
||||
return nil, ErrAdminRequired
|
||||
}
|
||||
return repository.ListActivePurchasers(db)
|
||||
}
|
||||
|
||||
// AssignClient 由管理员完成首次绑定或转交。
|
||||
func AssignClient(db *sql.DB, actor *model.User, clientID, purchaserUserID string, now time.Time) (bool, bool, error) {
|
||||
if actor == nil || !actor.IsAdmin() {
|
||||
return false, false, ErrAdminRequired
|
||||
}
|
||||
clientID = strings.TrimSpace(clientID)
|
||||
purchaserUserID = strings.TrimSpace(purchaserUserID)
|
||||
if clientID == "" || purchaserUserID == "" {
|
||||
return false, false, invalidInput("客户端和采购员都不能为空")
|
||||
}
|
||||
id, err := randomID("CA-", 16)
|
||||
if err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
at := now.UTC().Format(model.TimeLayout)
|
||||
return repository.AssignClient(db, model.ClientUserAssignment{
|
||||
AssignmentID: id, ClientID: clientID, UserID: purchaserUserID,
|
||||
StartedAt: at, AssignedByUserID: actor.UserID,
|
||||
})
|
||||
}
|
||||
|
||||
// UnassignClient 由管理员结束当前归属,不改动任何任务。
|
||||
func UnassignClient(db *sql.DB, actor *model.User, clientID string, now time.Time) error {
|
||||
if actor == nil || !actor.IsAdmin() {
|
||||
return ErrAdminRequired
|
||||
}
|
||||
clientID = strings.TrimSpace(clientID)
|
||||
if clientID == "" {
|
||||
return invalidInput("客户端不能为空")
|
||||
}
|
||||
return repository.UnassignClient(db, clientID, actor.UserID, now.UTC().Format(model.TimeLayout))
|
||||
}
|
||||
|
||||
// DeleteClients 批量删除,返回实际删除条数。
|
||||
func DeleteClients(db *sql.DB, clientIDs []string) (int64, error) {
|
||||
return repository.DeleteClients(db, clientIDs)
|
||||
|
||||
Reference in New Issue
Block a user