223 lines
6.7 KiB
TypeScript
223 lines
6.7 KiB
TypeScript
import axios from "axios";
|
|
|
|
import { buildCommanderHeaders, resolveCommanderBaseUrl } from "./commanderHttp";
|
|
|
|
export type CompetenciaStatus = "em_aberto" | "concluido";
|
|
|
|
export type CompetenciaItem = {
|
|
id: string;
|
|
mes: number;
|
|
ano: number;
|
|
status: CompetenciaStatus;
|
|
quantidadeFechamentos: number;
|
|
criadoEm: string;
|
|
atualizadoEm: string;
|
|
};
|
|
|
|
export type FechamentoDaCompetenciaItem = {
|
|
id: string;
|
|
competenciaId: string;
|
|
parceiroId: string;
|
|
parceiroNome: string;
|
|
parceiroCodinome: string | null;
|
|
parceiroLogoUrl: string | null;
|
|
parceiroFator?: number | null;
|
|
horasTotal: number;
|
|
status: "em_aberto" | "fechado";
|
|
versao: number;
|
|
pontuacaoTotalEntregue: number;
|
|
pontuacaoAprovada: number;
|
|
pontuacaoMeta: number;
|
|
pontuacaoPaga: number;
|
|
pontuacaoBanco: number;
|
|
exportadoFinanceiro: boolean;
|
|
fechadoPorId: string | null;
|
|
fechadoEm: string | null;
|
|
criadoEm: string;
|
|
atualizadoEm: string;
|
|
};
|
|
|
|
type ListarCompetenciasResponse = {
|
|
data: CompetenciaItem[];
|
|
};
|
|
|
|
type ListarFechamentosDaCompetenciaResponse = {
|
|
data: FechamentoDaCompetenciaItem[];
|
|
};
|
|
|
|
type CriarCompetenciaResponse = {
|
|
data: CompetenciaItem;
|
|
};
|
|
|
|
type ConcluirCompetenciaResponse = {
|
|
data: CompetenciaItem & {
|
|
concluidoPorNome: string | null;
|
|
};
|
|
};
|
|
|
|
type ReabrirCompetenciaResponse = {
|
|
data: CompetenciaItem & {
|
|
reabertoPorNome: string | null;
|
|
};
|
|
};
|
|
|
|
type ImportarCompetenciaResponse = {
|
|
data: {
|
|
competenciaId: string;
|
|
tarefasRecebidas: number;
|
|
tarefasImportadas: number;
|
|
fechamentosCriados: number;
|
|
tarefasIgnoradasSemParceiro: number;
|
|
chamadasSubtarefasAsana: number;
|
|
};
|
|
};
|
|
|
|
export type ImportacaoAsanaModo =
|
|
| "reprocessar_tudo"
|
|
| "reprocessar_alguns"
|
|
| "buscar_novos_fechamentos";
|
|
|
|
type ApiErrorShape = {
|
|
error?: {
|
|
message?: string;
|
|
};
|
|
};
|
|
|
|
class FechamentoCompetenciasService {
|
|
private handleAxiosError(error: unknown, fallback: string): never {
|
|
if (axios.isAxiosError(error)) {
|
|
if (!error.response) {
|
|
throw new Error(
|
|
"Não foi possível conectar na API do Commander. Verifique VITE_API_BASE_URL_COMMANDER e se o backend está acessível.",
|
|
);
|
|
}
|
|
const message = ((error.response.data as ApiErrorShape | undefined)?.error?.message ??
|
|
error.message ??
|
|
fallback) as string;
|
|
throw new Error(message);
|
|
}
|
|
throw new Error(fallback);
|
|
}
|
|
|
|
async listarCompetencias(params: { ano?: number; status?: CompetenciaStatus }): Promise<CompetenciaItem[]> {
|
|
try {
|
|
const headers = await buildCommanderHeaders();
|
|
const baseUrl = resolveCommanderBaseUrl();
|
|
const response = await axios.get<ListarCompetenciasResponse>(`${baseUrl}/competencias`, {
|
|
headers,
|
|
params: {
|
|
ano: params.ano,
|
|
status: params.status,
|
|
},
|
|
});
|
|
return response.data.data ?? [];
|
|
} catch (error) {
|
|
this.handleAxiosError(error, "Erro ao listar competências.");
|
|
}
|
|
}
|
|
|
|
async listarFechamentosDaCompetencia(competenciaId: string): Promise<FechamentoDaCompetenciaItem[]> {
|
|
try {
|
|
const headers = await buildCommanderHeaders();
|
|
const baseUrl = resolveCommanderBaseUrl();
|
|
const response = await axios.get<ListarFechamentosDaCompetenciaResponse>(
|
|
`${baseUrl}/competencias/${competenciaId}/fechamentos`,
|
|
{ headers },
|
|
);
|
|
return response.data.data ?? [];
|
|
} catch (error) {
|
|
this.handleAxiosError(error, "Erro ao listar fechamentos da competência.");
|
|
}
|
|
}
|
|
|
|
async criarCompetencia(input: { mes: number; ano: number }): Promise<CompetenciaItem> {
|
|
try {
|
|
const headers = await buildCommanderHeaders();
|
|
const baseUrl = resolveCommanderBaseUrl();
|
|
const response = await axios.post<CriarCompetenciaResponse>(
|
|
`${baseUrl}/competencias`,
|
|
{ mes: input.mes, ano: input.ano },
|
|
{ headers },
|
|
);
|
|
return response.data.data;
|
|
} catch (error) {
|
|
this.handleAxiosError(error, "Erro ao criar competência.");
|
|
}
|
|
}
|
|
|
|
async concluirCompetencia(competenciaId: string, concluidoPorId: string): Promise<ConcluirCompetenciaResponse["data"]> {
|
|
try {
|
|
const headers = await buildCommanderHeaders();
|
|
const baseUrl = resolveCommanderBaseUrl();
|
|
const response = await axios.post<ConcluirCompetenciaResponse>(
|
|
`${baseUrl}/competencias/${competenciaId}/concluir`,
|
|
{ concluido_por_id: concluidoPorId },
|
|
{ headers },
|
|
);
|
|
return response.data.data;
|
|
} catch (error) {
|
|
this.handleAxiosError(error, "Erro ao concluir competência.");
|
|
}
|
|
}
|
|
|
|
async reabrirCompetencia(
|
|
competenciaId: string,
|
|
reabertoPorId: string,
|
|
motivo: string,
|
|
): Promise<ReabrirCompetenciaResponse["data"]> {
|
|
try {
|
|
const headers = await buildCommanderHeaders();
|
|
const baseUrl = resolveCommanderBaseUrl();
|
|
const response = await axios.post<ReabrirCompetenciaResponse>(
|
|
`${baseUrl}/competencias/${competenciaId}/reabrir`,
|
|
{ reaberto_por_id: reabertoPorId, motivo: motivo.trim() },
|
|
{ headers },
|
|
);
|
|
return response.data.data;
|
|
} catch (error) {
|
|
this.handleAxiosError(error, "Erro ao reabrir competência.");
|
|
}
|
|
}
|
|
|
|
async excluirCompetencia(competenciaId: string, excluidoPorId: string): Promise<void> {
|
|
try {
|
|
const headers = await buildCommanderHeaders();
|
|
const baseUrl = resolveCommanderBaseUrl();
|
|
await axios.delete(`${baseUrl}/competencias/${competenciaId}`, {
|
|
headers,
|
|
data: { excluido_por_id: excluidoPorId },
|
|
});
|
|
} catch (error) {
|
|
this.handleAxiosError(error, "Erro ao excluir competência.");
|
|
}
|
|
}
|
|
|
|
async importarDoAsana(
|
|
competenciaId: string,
|
|
opcoes?: { modo?: ImportacaoAsanaModo; parceiroIds?: string[] },
|
|
): Promise<{ tarefasRecebidas: number; tarefasImportadas: number; fechamentosCriados: number; tarefasIgnoradasSemParceiro: number }> {
|
|
try {
|
|
const headers = await buildCommanderHeaders();
|
|
const baseUrl = resolveCommanderBaseUrl();
|
|
const response = await axios.post<ImportarCompetenciaResponse>(
|
|
`${baseUrl}/competencias/${competenciaId}/importar`,
|
|
{
|
|
modo: opcoes?.modo ?? "reprocessar_tudo",
|
|
parceiroIds: opcoes?.parceiroIds,
|
|
},
|
|
{ headers },
|
|
);
|
|
return {
|
|
tarefasRecebidas: response.data.data.tarefasRecebidas,
|
|
tarefasImportadas: response.data.data.tarefasImportadas,
|
|
fechamentosCriados: response.data.data.fechamentosCriados,
|
|
tarefasIgnoradasSemParceiro: response.data.data.tarefasIgnoradasSemParceiro,
|
|
};
|
|
} catch (error) {
|
|
this.handleAxiosError(error, "Erro ao importar tasks do Asana.");
|
|
}
|
|
}
|
|
}
|
|
|
|
export const fechamentoCompetenciasService = new FechamentoCompetenciasService();
|