TopSapp: fix API show blocked services from client

Signed-off-by: Rodrigo Bertoldo de Sousa Martins <rodrigo.sousa.577@gmail.com>
This commit is contained in:
rodrigo committed 2025-12-12 12:27:02 -03:00
1 parent 670dfed4bc
commit b794418d81
4 files changed
+994 -1689

No files matched your search

+48
View File
@@ -0,0 +1,48 @@
# GitHub Copilot Instructions
You are an expert senior software engineer focused on reliability, security, and clean architecture. Your primary goal is to implement exactly what the user requests without unnecessary bloat, ensuring zero regressions.
## 1. Core Principles (Non-Negotiable)
- **Safety First:** Never output code that could break the build, introduce security vulnerabilities, or delete existing functionality unless explicitly requested.
- **Minimal Footprint:** When generating files, aim for the smallest number of files necessary. Do not create multiple small files if a single, well-organized module suffices. Keep the file structure logical and flat where possible.
- **High Fidelity:** Implement *exactly* what is requested. Do not add "nice-to-have" features, speculative code, or extra dependencies unless they are critical for the requested functionality to work.
- **Idempotency:** Ensure that scripts and database migrations are idempotent (can be run multiple times without side effects).
## 2. TopSapp API Integration
**CRITICAL:** Whenever the user request involves interacting with the TopSapp system, you MUST consult the documentation located at:
`material/ManualApiTopSapp.txt`
- **Do not guess endpoints.** Use only the endpoints, methods (GET/POST), and payload structures defined in that manual.
- **Error Handling:** Always implement robust error handling for API calls (timeouts, 4xx/5xx responses) based on the patterns found in the manual.
- **Authentication:** Ensure the correct authentication headers/tokens are used as described in the manual.
## 3. Code Generation Rules
### A. Refactoring & Modification
- When modifying existing files, preserve the existing coding style (indentation, naming conventions).
- **Context Awareness:** Read the surrounding code to understand the scope. Do not overwrite imports or global variables unless necessary.
- **Comments:** Add concise comments explaining *why* a complex change was made, not just *what* the code does.
### B. New Features
- **Modularity:** Encapsulate new logic in functions or classes. Avoid polluting the global namespace.
- **Validation:** Always validate inputs before processing them, especially when dealing with external APIs like TopSapp.
### C. Testing
- If asked to generate tests, prioritize integration tests for API calls (mocking the actual TopSapp API) and unit tests for business logic.
## 4. Response Format
- **Plan First:** Before generating code for complex tasks, briefly outline the files you will create or modify.
- **Complete Code:** Do not use placeholders like `// ... rest of code`. Output the full, functional block of code needed for the file.
- **Verification:** After generating code, review it against the `material/ManualApiTopSapp.txt` to ensure compliance.
## 5. "Do No Harm" Checklist
Before outputting the final response, ask yourself:
1. Does this break existing features?
2. Did I invent an API endpoint that doesn't exist in the manual?
3. Is this the simplest way to solve the problem?
If the answer to 1 or 2 is "Yes", or 3 is "No", revise your solution immediately.
+830 -1685
View File
File diff suppressed because it is too large. Load diff
+73 -4
View File
@@ -508,10 +508,18 @@ class TopSappAPI {
if (response.success && response.data) { if (response.success && response.data) {
console.log(`✅ Sucesso na tentativa ${i + 1} - Total de itens: ${response.data.dados?.length || response.data.length || 0}`); console.log(`✅ Sucesso na tentativa ${i + 1} - Total de itens: ${response.data.dados?.length || response.data.length || 0}`);
logger.debug(`Sucesso na tentativa ${i + 1}`, {
totalItems: response.data.dados?.length || response.data.length || 0, // Normalizar os dados de status dos serviços
hasData: !!response.data if (response.data.dados && Array.isArray(response.data.dados)) {
}); response.data.dados = response.data.dados.map(servico => ({
...servico,
// Garantir que id_status está consistente
id_status: this.interpretarStatusServico(servico),
status: this.obterTextoStatus(this.interpretarStatusServico(servico))
}));
console.log(`🔄 Status dos serviços normalizados`);
}
// Verificar se os dados são relevantes para o cliente // Verificar se os dados são relevantes para o cliente
const dados = response.data.dados || response.data; const dados = response.data.dados || response.data;
@@ -551,6 +559,67 @@ class TopSappAPI {
return response; return response;
} }
/**
* Interpretar status do serviço corretamente
*/
interpretarStatusServico(servico) {
// Verificar diferentes campos de status
// Se tem id_status explícito, usar ele
if (servico.id_status) {
return parseInt(servico.id_status, 10);
}
// Interpretar pelo campo status textual
if (servico.status) {
const statusLower = servico.status.toLowerCase();
if (statusLower.includes('liberado') || statusLower.includes('ativo')) {
return 1; // Ativo/Liberado
}
if (statusLower.includes('bloqueado')) {
return 2; // Bloqueado
}
if (statusLower.includes('desativado') || statusLower.includes('inativo')) {
return 3; // Desativado
}
}
// Verificar por datas
if (servico.data_desativacao && servico.data_desativacao !== '0000-00-00' && servico.data_desativacao !== null) {
return 3; // Desativado
}
if (servico.data_bloqueio && servico.data_bloqueio !== '0000-00-00' && servico.data_bloqueio !== null) {
// Verificar se foi desbloqueado depois
if (!servico.data_desbloqueio || servico.data_desbloqueio === '0000-00-00' || servico.data_desbloqueio === null) {
return 2; // Bloqueado
}
// Se tem data de desbloqueio, verificar qual é mais recente
if (new Date(servico.data_desbloqueio) < new Date(servico.data_bloqueio)) {
return 2; // Bloqueado (bloqueio é mais recente)
}
}
// Por padrão, considerar ativo
return 1;
}
/**
* Obter texto descritivo do status
*/
obterTextoStatus(idStatus) {
switch (parseInt(idStatus, 10)) {
case 1: return 'liberado';
case 2: return 'bloqueado';
case 3: return 'desativado';
default: return 'desconhecido';
}
}
/** /**
* Obter faturas em aberto do cliente * Obter faturas em aberto do cliente
*/ */
+43
View File
@@ -1165,6 +1165,49 @@ class TopSappManager {
return 'Período não informado'; return 'Período não informado';
} }
} }
/**
* Alias para obterServicosCliente
*/
async obterServicos(idCliente, location = '') {
return await this.obterServicosCliente(idCliente, location);
}
/**
* Alias para bloquearServicoEspecifico
*/
async bloquearServico(idServico, idCliente, location = '') {
return await this.bloquearServicoEspecifico(idCliente, idServico, location);
}
/**
* Alias para liberarServicoEspecifico
*/
async liberarServico(idServico, idCliente, location = '') {
return await this.liberarServicoEspecifico(idCliente, idServico, location);
}
/**
* Obter faturas do cliente
*/
async obterFaturas(idCliente, location = '') {
if (!this.isReady()) {
return {
success: false,
error: 'TopSapp não está configurado'
};
}
try {
const credentials = this.config.getCredentialsByLocation(location);
return await this.api.obterFaturas(idCliente, location, credentials);
} catch (error) {
return {
success: false,
error: error.message
};
}
}
} }
module.exports = TopSappManager; module.exports = TopSappManager;