ajustes
This commit is contained in:
296
main.go
296
main.go
@@ -845,6 +845,206 @@ func formatChargeabilityForLLM(result []ProfissionalChargeability, args Chargeab
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// ── Tool: pesquisar_usuarios / get_usuario ──
|
||||
|
||||
type UsuarioResumo struct {
|
||||
Nome string `json:"nome"`
|
||||
Email string `json:"email"`
|
||||
Cargo string `json:"cargo"`
|
||||
Ativo string `json:"ativo"`
|
||||
Disponivel string `json:"disponivel"`
|
||||
}
|
||||
|
||||
func pesquisarUsuarios(busca string) ([]UsuarioResumo, error) {
|
||||
token, cookie, err := qualitorLogin()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
safe := safeSQLString(busca)
|
||||
like := "%" + safe + "%"
|
||||
|
||||
sql := `SELECT u.nmusuario, u.dsemail, u.idativo, u.iddisponivel, c.nmcargo
|
||||
FROM QUALITOR.dbo.ad_usuario u
|
||||
LEFT JOIN QUALITOR.dbo.ad_cargo c ON c.cdcargo = u.cdcargo
|
||||
WHERE (u.nmusuario LIKE '` + like + `' OR u.dsemail LIKE '` + like + `' OR u.nmusuariorede LIKE '` + like + `')
|
||||
AND u.idativo = 'Y'
|
||||
ORDER BY u.nmusuario`
|
||||
|
||||
xmlResult, err := qualitorQuery(token, cookie, sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
decoded := extractResult(xmlResult)
|
||||
items := extractDataItems(decoded)
|
||||
var usuarios []UsuarioResumo
|
||||
for _, block := range items {
|
||||
f := extractAllFields(block)
|
||||
usuarios = append(usuarios, UsuarioResumo{
|
||||
Nome: f["nmusuario"],
|
||||
Email: f["dsemail"],
|
||||
Cargo: f["nmcargo"],
|
||||
Ativo: f["idativo"],
|
||||
Disponivel: f["iddisponivel"],
|
||||
})
|
||||
}
|
||||
return usuarios, nil
|
||||
}
|
||||
|
||||
type UsuarioDetalhado struct {
|
||||
Nome string `json:"nome"`
|
||||
Email string `json:"email"`
|
||||
Login string `json:"login"`
|
||||
Cargo string `json:"cargo"`
|
||||
Superior string `json:"superior"`
|
||||
Ativo string `json:"ativo"`
|
||||
Disponivel string `json:"disponivel"`
|
||||
Bloqueado string `json:"bloqueado"`
|
||||
Equipes []string `json:"equipes"`
|
||||
Total30d string `json:"total_chamados_30d"`
|
||||
Terminados string `json:"terminados_30d"`
|
||||
Abertos string `json:"abertos_30d"`
|
||||
}
|
||||
|
||||
func getUsuario(nome string) (*UsuarioDetalhado, error) {
|
||||
token, cookie, err := qualitorLogin()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
safe := safeSQLString(nome)
|
||||
|
||||
// Dados do usuario
|
||||
sqlUser := `SELECT u.nmusuario, u.dsemail, u.nmusuariorede, u.idativo, u.iddisponivel, u.idbloqueado,
|
||||
c.nmcargo, s.nmusuario AS superior
|
||||
FROM QUALITOR.dbo.ad_usuario u
|
||||
LEFT JOIN QUALITOR.dbo.ad_cargo c ON c.cdcargo = u.cdcargo
|
||||
LEFT JOIN QUALITOR.dbo.ad_usuario s ON s.cdusuario = u.cdusuariosuperior
|
||||
WHERE u.nmusuario = '` + safe + `'`
|
||||
|
||||
// Equipes
|
||||
sqlEquipes := `SELECT e.nmequipe
|
||||
FROM QUALITOR.dbo.hd_equipe e
|
||||
JOIN QUALITOR.dbo.hd_equipeusuario eu ON eu.cdequipe = e.cdequipe
|
||||
JOIN QUALITOR.dbo.ad_usuario u ON u.cdusuario = eu.cdusuario
|
||||
WHERE u.nmusuario = '` + safe + `'
|
||||
ORDER BY e.nmequipe`
|
||||
|
||||
// Stats 30 dias
|
||||
sqlStats := `SELECT
|
||||
COUNT(*) AS total,
|
||||
SUM(CASE WHEN STATUS = 'TERMINADO' THEN 1 ELSE 0 END) AS terminados,
|
||||
SUM(CASE WHEN STATUS NOT IN ('TERMINADO','Cancelado') THEN 1 ELSE 0 END) AS abertos
|
||||
FROM lgit_chamados
|
||||
WHERE ATENDENTE = '` + safe + `' AND DATA_ABERTURA >= DATEADD(DAY, -30, GETDATE())`
|
||||
|
||||
xmlUser, err := qualitorQuery(token, cookie, sqlUser)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
xmlEquipes, err := qualitorQuery(token, cookie, sqlEquipes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
xmlStats, err := qualitorQuery(token, cookie, sqlStats)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Parse user
|
||||
decoded := extractResult(xmlUser)
|
||||
items := extractDataItems(decoded)
|
||||
if len(items) == 0 {
|
||||
return nil, fmt.Errorf("usuário '%s' não encontrado", nome)
|
||||
}
|
||||
f := extractAllFields(items[0])
|
||||
|
||||
result := &UsuarioDetalhado{
|
||||
Nome: f["nmusuario"],
|
||||
Email: f["dsemail"],
|
||||
Login: f["nmusuariorede"],
|
||||
Cargo: f["nmcargo"],
|
||||
Superior: f["superior"],
|
||||
Ativo: f["idativo"],
|
||||
Disponivel: f["iddisponivel"],
|
||||
Bloqueado: f["idbloqueado"],
|
||||
}
|
||||
|
||||
// Parse equipes
|
||||
decodedEq := extractResult(xmlEquipes)
|
||||
eqItems := extractDataItems(decodedEq)
|
||||
for _, block := range eqItems {
|
||||
eq := extractField(block, "nmequipe")
|
||||
if eq != "" {
|
||||
result.Equipes = append(result.Equipes, eq)
|
||||
}
|
||||
}
|
||||
|
||||
// Parse stats
|
||||
decodedSt := extractResult(xmlStats)
|
||||
stItems := extractDataItems(decodedSt)
|
||||
if len(stItems) > 0 {
|
||||
sf := extractAllFields(stItems[0])
|
||||
result.Total30d = sf["total"]
|
||||
result.Terminados = sf["terminados"]
|
||||
result.Abertos = sf["abertos"]
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func formatUsuarioForLLM(u *UsuarioDetalhado) string {
|
||||
var b strings.Builder
|
||||
b.WriteString(fmt.Sprintf("# Usuário: %s\n\n", u.Nome))
|
||||
b.WriteString(fmt.Sprintf("**E-mail:** %s\n", u.Email))
|
||||
b.WriteString(fmt.Sprintf("**Login:** %s\n", u.Login))
|
||||
b.WriteString(fmt.Sprintf("**Cargo:** %s\n", u.Cargo))
|
||||
b.WriteString(fmt.Sprintf("**Superior:** %s\n", u.Superior))
|
||||
|
||||
status := "Ativo"
|
||||
if u.Ativo != "Y" {
|
||||
status = "Inativo"
|
||||
}
|
||||
if u.Bloqueado == "S" {
|
||||
status += " (Bloqueado)"
|
||||
}
|
||||
b.WriteString(fmt.Sprintf("**Status:** %s | **Disponível:** %s\n", status, u.Disponivel))
|
||||
|
||||
if len(u.Equipes) > 0 {
|
||||
b.WriteString(fmt.Sprintf("**Equipes:** %s\n", strings.Join(u.Equipes, ", ")))
|
||||
}
|
||||
|
||||
b.WriteString(fmt.Sprintf("\n## Chamados (últimos 30 dias)\n"))
|
||||
b.WriteString(fmt.Sprintf("- Total: %s\n", u.Total30d))
|
||||
b.WriteString(fmt.Sprintf("- Terminados: %s\n", u.Terminados))
|
||||
b.WriteString(fmt.Sprintf("- Em aberto: %s\n", u.Abertos))
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func formatPesquisaUsuariosForLLM(usuarios []UsuarioResumo, busca string) string {
|
||||
var b strings.Builder
|
||||
b.WriteString(fmt.Sprintf("# Pesquisa de Usuários (%d resultados)\n\n", len(usuarios)))
|
||||
b.WriteString(fmt.Sprintf("**Busca:** \"%s\"\n\n", busca))
|
||||
|
||||
if len(usuarios) == 0 {
|
||||
b.WriteString("Nenhum usuário encontrado.\n")
|
||||
return b.String()
|
||||
}
|
||||
|
||||
b.WriteString("| Nome | E-mail | Cargo | Disponível |\n")
|
||||
b.WriteString("|------|--------|-------|------------|\n")
|
||||
for _, u := range usuarios {
|
||||
disp := "Sim"
|
||||
if u.Disponivel != "Y" {
|
||||
disp = "Não"
|
||||
}
|
||||
b.WriteString(fmt.Sprintf("| %s | %s | %s | %s |\n", u.Nome, u.Email, u.Cargo, disp))
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func filterEmpty(ss []string) []string {
|
||||
var out []string
|
||||
for _, s := range ss {
|
||||
@@ -990,6 +1190,34 @@ func handleToolsList(id json.RawMessage, w io.Writer) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "pesquisar_usuarios",
|
||||
"description": "Pesquisa usuários ativos no Qualitor por nome, e-mail ou login de rede. Retorna nome, e-mail, cargo e disponibilidade.",
|
||||
"inputSchema": map[string]interface{}{
|
||||
"type": "object",
|
||||
"properties": map[string]interface{}{
|
||||
"busca": map[string]interface{}{
|
||||
"type": "string",
|
||||
"description": "Texto para buscar no nome, e-mail ou login do usuário (ex: 'Odilon', 'odilon.silva', 'grupothink')",
|
||||
},
|
||||
},
|
||||
"required": []string{"busca"},
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "get_usuario",
|
||||
"description": "Busca informações detalhadas de um usuário no Qualitor pelo nome completo. Retorna dados pessoais (e-mail, login, cargo, superior hierárquico), equipes que participa, status (ativo/bloqueado/disponível) e estatísticas de chamados dos últimos 30 dias.",
|
||||
"inputSchema": map[string]interface{}{
|
||||
"type": "object",
|
||||
"properties": map[string]interface{}{
|
||||
"nome": map[string]interface{}{
|
||||
"type": "string",
|
||||
"description": "Nome completo do usuário no Qualitor (ex: 'Odilon Pascoal Mendes Silva')",
|
||||
},
|
||||
},
|
||||
"required": []string{"nome"},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1081,6 +1309,74 @@ func handleToolCall(id json.RawMessage, params json.RawMessage, w io.Writer) {
|
||||
},
|
||||
})
|
||||
|
||||
case "pesquisar_usuarios":
|
||||
var args struct {
|
||||
Busca string `json:"busca"`
|
||||
}
|
||||
json.Unmarshal(p.Arguments, &args)
|
||||
|
||||
if args.Busca == "" {
|
||||
sendResponse(w, id, map[string]interface{}{
|
||||
"content": []map[string]interface{}{
|
||||
{"type": "text", "text": "Erro: campo 'busca' é obrigatório"},
|
||||
},
|
||||
"isError": true,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
usuarios, err := pesquisarUsuarios(args.Busca)
|
||||
if err != nil {
|
||||
sendResponse(w, id, map[string]interface{}{
|
||||
"content": []map[string]interface{}{
|
||||
{"type": "text", "text": fmt.Sprintf("Erro: %s", err.Error())},
|
||||
},
|
||||
"isError": true,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
text := formatPesquisaUsuariosForLLM(usuarios, args.Busca)
|
||||
sendResponse(w, id, map[string]interface{}{
|
||||
"content": []map[string]interface{}{
|
||||
{"type": "text", "text": text},
|
||||
},
|
||||
})
|
||||
|
||||
case "get_usuario":
|
||||
var args struct {
|
||||
Nome string `json:"nome"`
|
||||
}
|
||||
json.Unmarshal(p.Arguments, &args)
|
||||
|
||||
if args.Nome == "" {
|
||||
sendResponse(w, id, map[string]interface{}{
|
||||
"content": []map[string]interface{}{
|
||||
{"type": "text", "text": "Erro: campo 'nome' é obrigatório"},
|
||||
},
|
||||
"isError": true,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
usuario, err := getUsuario(args.Nome)
|
||||
if err != nil {
|
||||
sendResponse(w, id, map[string]interface{}{
|
||||
"content": []map[string]interface{}{
|
||||
{"type": "text", "text": fmt.Sprintf("Erro: %s", err.Error())},
|
||||
},
|
||||
"isError": true,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
text := formatUsuarioForLLM(usuario)
|
||||
sendResponse(w, id, map[string]interface{}{
|
||||
"content": []map[string]interface{}{
|
||||
{"type": "text", "text": text},
|
||||
},
|
||||
})
|
||||
|
||||
default:
|
||||
sendResponse(w, id, map[string]interface{}{
|
||||
"content": []map[string]interface{}{
|
||||
|
||||
Reference in New Issue
Block a user