diff --git a/docs/docs.go b/docs/docs.go index c5c7825..aff2975 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -195,6 +195,50 @@ const docTemplate = `{ } } }, + "/uiapi/v2/orgao/media/{ano}": { + "get": { + "description": "Busca médias (remuneração base, outras remunerações, descontos e remuneração total) de cada órgão em um ano especificado.", + "produces": [ + "application/json" + ], + "tags": [ + "ui_api" + ], + "operationId": "GetAveragePerAgency", + "parameters": [ + { + "type": "integer", + "description": "Ano para filtrar os dados", + "name": "ano", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Lista de dados de médias dos órgãos", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/uiapi.averagePerAgency" + } + } + }, + "400": { + "description": "Parâmetro ANO inválido", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Erro ao buscar dados", + "schema": { + "type": "string" + } + } + } + } + }, "/uiapi/v2/orgao/resumo/{orgao}/{ano}/{mes}": { "get": { "description": "Endpoint de resumo das remunerações mensal de um órgão. Fornece uma análise financeira abrangente para um órgão específico em um mês e ano determinados\n\nInformações Financeiras Detalhadas:\n- Remuneração base total e máxima\n- Outras remunerações e benefícios\n- Valor total de descontos\n- Contagem de membros\n- Análise de rubricas (penduricalhos) específicas\n\nContexto Adicional:\n- Marcadores de existência de dados anteriores/posteriores ao ano/mês consultados\n- Timestamp da coleta de dados\n- Detalhamento de diferentes tipos de remuneração (remuneração base, outras remunerações e descontos)", @@ -1578,6 +1622,17 @@ const docTemplate = `{ } } }, + "uiapi.averagePerAgency": { + "type": "object", + "properties": { + "id_orgao": { + "type": "string" + }, + "media_por_membro": { + "$ref": "#/definitions/uiapi.perCapitaData" + } + } + }, "uiapi.backup": { "type": "object", "properties": { @@ -1754,6 +1809,12 @@ const docTemplate = `{ "categoria_contracheque": { "type": "string" }, + "desambiguacao_macro": { + "type": "string" + }, + "desambiguacao_micro": { + "type": "string" + }, "detalhamento_contracheque": { "type": "string" }, diff --git a/docs/swagger.json b/docs/swagger.json index 7d11e09..9156208 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -186,6 +186,50 @@ } } }, + "/uiapi/v2/orgao/media/{ano}": { + "get": { + "description": "Busca médias (remuneração base, outras remunerações, descontos e remuneração total) de cada órgão em um ano especificado.", + "produces": [ + "application/json" + ], + "tags": [ + "ui_api" + ], + "operationId": "GetAveragePerAgency", + "parameters": [ + { + "type": "integer", + "description": "Ano para filtrar os dados", + "name": "ano", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Lista de dados de médias dos órgãos", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/uiapi.averagePerAgency" + } + } + }, + "400": { + "description": "Parâmetro ANO inválido", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Erro ao buscar dados", + "schema": { + "type": "string" + } + } + } + } + }, "/uiapi/v2/orgao/resumo/{orgao}/{ano}/{mes}": { "get": { "description": "Endpoint de resumo das remunerações mensal de um órgão. Fornece uma análise financeira abrangente para um órgão específico em um mês e ano determinados\n\nInformações Financeiras Detalhadas:\n- Remuneração base total e máxima\n- Outras remunerações e benefícios\n- Valor total de descontos\n- Contagem de membros\n- Análise de rubricas (penduricalhos) específicas\n\nContexto Adicional:\n- Marcadores de existência de dados anteriores/posteriores ao ano/mês consultados\n- Timestamp da coleta de dados\n- Detalhamento de diferentes tipos de remuneração (remuneração base, outras remunerações e descontos)", @@ -1569,6 +1613,17 @@ } } }, + "uiapi.averagePerAgency": { + "type": "object", + "properties": { + "id_orgao": { + "type": "string" + }, + "media_por_membro": { + "$ref": "#/definitions/uiapi.perCapitaData" + } + } + }, "uiapi.backup": { "type": "object", "properties": { @@ -1745,6 +1800,12 @@ "categoria_contracheque": { "type": "string" }, + "desambiguacao_macro": { + "type": "string" + }, + "desambiguacao_micro": { + "type": "string" + }, "detalhamento_contracheque": { "type": "string" }, diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 5edc3f5..d1ab9a8 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -379,6 +379,13 @@ definitions: resumo_rubricas: $ref: '#/definitions/uiapi.itemSummary' type: object + uiapi.averagePerAgency: + properties: + id_orgao: + type: string + media_por_membro: + $ref: '#/definitions/uiapi.perCapitaData' + type: object uiapi.backup: properties: hash: @@ -495,6 +502,10 @@ definitions: type: string categoria_contracheque: type: string + desambiguacao_macro: + type: string + desambiguacao_micro: + type: string detalhamento_contracheque: type: string lotacao: @@ -829,6 +840,36 @@ paths: type: string tags: - ui_api + /uiapi/v2/orgao/media/{ano}: + get: + description: Busca médias (remuneração base, outras remunerações, descontos + e remuneração total) de cada órgão em um ano especificado. + operationId: GetAveragePerAgency + parameters: + - description: Ano para filtrar os dados + in: path + name: ano + required: true + type: integer + produces: + - application/json + responses: + "200": + description: Lista de dados de médias dos órgãos + schema: + items: + $ref: '#/definitions/uiapi.averagePerAgency' + type: array + "400": + description: Parâmetro ANO inválido + schema: + type: string + "500": + description: Erro ao buscar dados + schema: + type: string + tags: + - ui_api /uiapi/v2/orgao/resumo/{orgao}/{ano}/{mes}: get: description: |- diff --git a/go.mod b/go.mod index 0ada724..8f0f8c3 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ toolchain go1.23.9 require ( github.com/dadosjusbr/proto v0.0.0-20221212025627-91c60aa3cd12 - github.com/dadosjusbr/storage v0.0.0-20250521134559-e17ec6ce3c9b + github.com/dadosjusbr/storage v0.0.0-20250527175952-898e1b7ea3a3 github.com/gocarina/gocsv v0.0.0-20220712153207-8b2118da4570 github.com/golang/mock v1.6.0 github.com/joho/godotenv v1.4.0 diff --git a/go.sum b/go.sum index 10fb437..ea2351d 100644 --- a/go.sum +++ b/go.sum @@ -14,6 +14,8 @@ github.com/dadosjusbr/proto v0.0.0-20221212025627-91c60aa3cd12 h1:ufl8nbCEo6g2VH github.com/dadosjusbr/proto v0.0.0-20221212025627-91c60aa3cd12/go.mod h1:gPA7VxjEmyez/xtln4qBj+tM1NO0/zcw3ryjxTRNSco= github.com/dadosjusbr/storage v0.0.0-20250521134559-e17ec6ce3c9b h1:9hBbtKGqpa+njukDDsOTSJZBF/ixStpoHlZ3rJRI7LY= github.com/dadosjusbr/storage v0.0.0-20250521134559-e17ec6ce3c9b/go.mod h1:y6Oi2/v4ebsTfgY8/ACqIA7IEApU8MoCRNBCl1iSlmI= +github.com/dadosjusbr/storage v0.0.0-20250527175952-898e1b7ea3a3 h1:yKu3lkCzvEtBjNY9FoBEHociNfazpnXhO6QKWFQxKx0= +github.com/dadosjusbr/storage v0.0.0-20250527175952-898e1b7ea3a3/go.mod h1:y6Oi2/v4ebsTfgY8/ACqIA7IEApU8MoCRNBCl1iSlmI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/main.go b/main.go index 8168f56..8ac7338 100644 --- a/main.go +++ b/main.go @@ -82,10 +82,10 @@ func newS3Client(c config) (*file_storage.S3Client, error) { return s3Client, nil } -// @title API do dadosjusbr.org -// @version 1.0 -// @contact.name DadosJusBr -// @contact.url https://dadosjusbr.org +// @title API do dadosjusbr.org +// @version 1.0 +// @contact.name DadosJusBr +// @contact.url https://dadosjusbr.org func main() { godotenv.Load() // There is no problem if the .env can not be loaded. l, err := time.LoadLocation("America/Sao_Paulo") @@ -199,7 +199,10 @@ func main() { uiAPIGroup.GET("/v2/pesquisar", uiApiHandler.SearchByUrl) // Baixa um conjunto de dados a partir de filtros informados por query params uiAPIGroup.GET("/v2/download", uiApiHandler.DownloadByUrl) + // Baixa o readme do pacote de dados uiAPIGroup.GET("/v2/readme", uiApiHandler.DownloadReadme) + // Retorna a média (base, benefícios, descontos e remuneração) de cada órgão em um ano + uiAPIGroup.GET("/v2/orgao/media/:ano", uiApiHandler.GetAveragePerAgency) apiHandler := papi.NewHandler(pgS3Client, conf.DadosJusURL, conf.PackageRepoURL) // Public API configuration diff --git a/uiapi/handlers.go b/uiapi/handlers.go index 064ea2b..72727b3 100644 --- a/uiapi/handlers.go +++ b/uiapi/handlers.go @@ -81,30 +81,30 @@ func (h handler) GetSummaryOfAgency(c echo.Context) error { return c.JSON(http.StatusOK, agencySummary) } -// @ID GetSummaryOfAgency -// @Tags ui_api -// @Description Endpoint de resumo das remunerações mensal de um órgão. Fornece uma análise financeira abrangente para um órgão específico em um mês e ano determinados -// @Description -// @Description Informações Financeiras Detalhadas: -// @Description - Remuneração base total e máxima -// @Description - Outras remunerações e benefícios -// @Description - Valor total de descontos -// @Description - Contagem de membros -// @Description - Análise de rubricas (penduricalhos) específicas -// @Description -// @Description Contexto Adicional: -// @Description - Marcadores de existência de dados anteriores/posteriores ao ano/mês consultados -// @Description - Timestamp da coleta de dados -// @Description - Detalhamento de diferentes tipos de remuneração (remuneração base, outras remunerações e descontos) -// @Produce json -// @Param orgao path string true "Sigla do órgão. Ex.: tjal, mppb, tjmmg" -// @Param mes path string true "Mês de referência (1-12)" -// @Param ano path string true "Ano de referência" -// @Success 200 {object} v2AgencySummary "Resumo financeiro do órgão processado com sucesso" -// @Failure 400 {string} string "Erro de validação dos parâmetros de entrada" -// @Failure 404 {string} string "Órgão ou dados não encontrados" -// @Failure 500 {string} string "Erro interno durante processamento da consulta" -// @Router /uiapi/v2/orgao/resumo/{orgao}/{ano}/{mes} [get] +// @ID GetSummaryOfAgency +// @Tags ui_api +// @Description Endpoint de resumo das remunerações mensal de um órgão. Fornece uma análise financeira abrangente para um órgão específico em um mês e ano determinados +// @Description +// @Description Informações Financeiras Detalhadas: +// @Description - Remuneração base total e máxima +// @Description - Outras remunerações e benefícios +// @Description - Valor total de descontos +// @Description - Contagem de membros +// @Description - Análise de rubricas (penduricalhos) específicas +// @Description +// @Description Contexto Adicional: +// @Description - Marcadores de existência de dados anteriores/posteriores ao ano/mês consultados +// @Description - Timestamp da coleta de dados +// @Description - Detalhamento de diferentes tipos de remuneração (remuneração base, outras remunerações e descontos) +// @Produce json +// @Param orgao path string true "Sigla do órgão. Ex.: tjal, mppb, tjmmg" +// @Param mes path string true "Mês de referência (1-12)" +// @Param ano path string true "Ano de referência" +// @Success 200 {object} v2AgencySummary "Resumo financeiro do órgão processado com sucesso" +// @Failure 400 {string} string "Erro de validação dos parâmetros de entrada" +// @Failure 404 {string} string "Órgão ou dados não encontrados" +// @Failure 500 {string} string "Erro interno durante processamento da consulta" +// @Router /uiapi/v2/orgao/resumo/{orgao}/{ano}/{mes} [get] func (h handler) V2GetSummaryOfAgency(c echo.Context) error { year, err := strconv.Atoi(c.Param("ano")) if err != nil { @@ -182,34 +182,34 @@ func (h handler) GetSalaryOfAgencyMonthYear(c echo.Context) error { }) } -// @ID GetSalaryOfAgencyMonthYear -// @Tags ui_api -// @Description Endpoint de análise detalhada de remunerações dos órgãos. Recupera informações financeiras granulares para um órgão específico em um mês e ano determinados -// @Description -// @Description Informações Fornecidos: -// @Description - Remuneração máxima no período -// @Description - Histograma de distribuição de rendimentos -// @Description - Metadados do pacote de dados -// @Description -// @Description Histograma de Distribuição de Rendimentos: -// @Description -// @Description O histograma apresenta a quantidade de membros que receberam diferentes faixas de remunerações em um determinado mês. -// @Description As faixas de remuneração são definidas da seguinte forma: -// @Description - 10000: quantidade de membros que receberam até R$ 10.000,00 -// @Description - 20000: quantidade de membros que receberam entre R$ 10.000,01 e R$ 20.000,00 -// @Description - 30000: quantidade de membros que receberam entre R$ 20.000,01 e R$ 30.000,00 -// @Description - 40000: quantidade de membros que receberam entre R$ 30.000,01 e R$ 40.000,00 -// @Description - 50000: quantidade de membros que receberam entre R$ 40.000,01 e R$ 50.000,00 -// @Description - -1: quantidade de membros que receberam acima de R$ 50.000,01 -// @Produce json -// @Param orgao path string true "Sigla do órgão. Ex.: tjal, mppb, tjmmg" -// @Param mes path string true "Mês de referência (1-12)" -// @Param ano path string true "Ano de referência" -// @Success 200 {object} agencyRemuneration "Dados de remuneração processados com sucesso" -// @Success 206 {object} v2ProcInfoResult "Dados coletados com informações de processamento" -// @Failure 400 {string} string "Erro de validação dos parâmetros de entrada" -// @Failure 500 {string} string "Erro interno durante processamento da consulta" -// @Router /uiapi/v2/orgao/salario/{orgao}/{ano}/{mes} [get] +// @ID GetSalaryOfAgencyMonthYear +// @Tags ui_api +// @Description Endpoint de análise detalhada de remunerações dos órgãos. Recupera informações financeiras granulares para um órgão específico em um mês e ano determinados +// @Description +// @Description Informações Fornecidos: +// @Description - Remuneração máxima no período +// @Description - Histograma de distribuição de rendimentos +// @Description - Metadados do pacote de dados +// @Description +// @Description Histograma de Distribuição de Rendimentos: +// @Description +// @Description O histograma apresenta a quantidade de membros que receberam diferentes faixas de remunerações em um determinado mês. +// @Description As faixas de remuneração são definidas da seguinte forma: +// @Description - 10000: quantidade de membros que receberam até R$ 10.000,00 +// @Description - 20000: quantidade de membros que receberam entre R$ 10.000,01 e R$ 20.000,00 +// @Description - 30000: quantidade de membros que receberam entre R$ 20.000,01 e R$ 30.000,00 +// @Description - 40000: quantidade de membros que receberam entre R$ 30.000,01 e R$ 40.000,00 +// @Description - 50000: quantidade de membros que receberam entre R$ 40.000,01 e R$ 50.000,00 +// @Description - -1: quantidade de membros que receberam acima de R$ 50.000,01 +// @Produce json +// @Param orgao path string true "Sigla do órgão. Ex.: tjal, mppb, tjmmg" +// @Param mes path string true "Mês de referência (1-12)" +// @Param ano path string true "Ano de referência" +// @Success 200 {object} agencyRemuneration "Dados de remuneração processados com sucesso" +// @Success 206 {object} v2ProcInfoResult "Dados coletados com informações de processamento" +// @Failure 400 {string} string "Erro de validação dos parâmetros de entrada" +// @Failure 500 {string} string "Erro interno durante processamento da consulta" +// @Router /uiapi/v2/orgao/salario/{orgao}/{ano}/{mes} [get] func (h handler) V2GetSalaryOfAgencyMonthYear(c echo.Context) error { month, err := strconv.Atoi(c.Param("mes")) if err != nil { @@ -322,28 +322,28 @@ func (h handler) GetTotalsOfAgencyYear(c echo.Context) error { return c.JSON(http.StatusOK, agencyTotalsYear) } -// @ID GetTotalsOfAgencyYear -// @Tags ui_api -// @Description Recupera dados financeiros detalhados para um órgão em um ano específico -// @Description -// @Description Dados Financeiros Mensais: -// @Description - Remuneração base -// @Description - Outras remunerações e benefícios -// @Description - Descontos -// @Description - Contagem de membros -// @Description -// @Description Métricas Adicionais: -// @Description - Médias per capita -// @Description - Detalhamento de rubricas (auxílios, férias, gratificações) -// @Description - Informações gerais sobre o órgão pesquisado -// @Description - Informações sobre o pacote de dados (URL para download, hash, tamanho) -// @Produce json -// @Param orgao path string true "Identificador do órgão público" example:"tjal" -// @Param ano path int true "Ano de referência para a consulta" example:"2022" -// @Success 200 {object} v2AgencyTotalsYear "Dados financeiros completos do órgão no ano especificado" -// @Failure 400 {string} string "Erro de validação: parâmetros de órgão ou ano inválidos" -// @Failure 500 {string} string "Erro interno durante processamento da consulta" -// @Router /uiapi/v2/orgao/totais/{orgao}/{ano} [get] +// @ID GetTotalsOfAgencyYear +// @Tags ui_api +// @Description Recupera dados financeiros detalhados para um órgão em um ano específico +// @Description +// @Description Dados Financeiros Mensais: +// @Description - Remuneração base +// @Description - Outras remunerações e benefícios +// @Description - Descontos +// @Description - Contagem de membros +// @Description +// @Description Métricas Adicionais: +// @Description - Médias per capita +// @Description - Detalhamento de rubricas (auxílios, férias, gratificações) +// @Description - Informações gerais sobre o órgão pesquisado +// @Description - Informações sobre o pacote de dados (URL para download, hash, tamanho) +// @Produce json +// @Param orgao path string true "Identificador do órgão público" example:"tjal" +// @Param ano path int true "Ano de referência para a consulta" example:"2022" +// @Success 200 {object} v2AgencyTotalsYear "Dados financeiros completos do órgão no ano especificado" +// @Failure 400 {string} string "Erro de validação: parâmetros de órgão ou ano inválidos" +// @Failure 500 {string} string "Erro interno durante processamento da consulta" +// @Router /uiapi/v2/orgao/totais/{orgao}/{ano} [get] func (h handler) V2GetTotalsOfAgencyYear(c echo.Context) error { year, err := strconv.Atoi(c.Param("ano")) if err != nil { @@ -522,15 +522,15 @@ func (h handler) GetBasicInfoOfType(c echo.Context) error { return c.JSON(http.StatusOK, state) } -// @ID GetBasicInfoOfType -// @Tags ui_api -// @Description Busca informações de id (sigla), nome e entidade (jurisdiçãso) de um determinado grupo de órgãos. Ao Selecionar um grupo de órgãos por estado (Ex.: RJ, SP, etc.), retorna as informações dos tribunais de justiça desse estado (entidade=Tribunal). -// @Produce json -// @Param grupo path string false "Grupo de órgãos" Enums(justica-eleitoral, ministerios-publicos, justica-estadual, justica-do-trabalho, justica-federal, justica-militar, justica-superior, conselhos-de-justica, AC, AL, AP, AM, BA, CE, DF, ES, GO, MA, MT, MS, MG, PA, PB, PR, PE, PI, RJ, RN, RS, RO, RR, SC, SP, SE, TO) -// @Success 200 {object} state "Órgãos do grupo" -// @Failure 400 {object} string "Parâmetro inválido" -// @Failure 404 {object} string "Grupo não encontrado" -// @Router /uiapi/v2/orgao/{grupo} [get] +// @ID GetBasicInfoOfType +// @Tags ui_api +// @Description Busca informações de id (sigla), nome e entidade (jurisdiçãso) de um determinado grupo de órgãos. Ao Selecionar um grupo de órgãos por estado (Ex.: RJ, SP, etc.), retorna as informações dos tribunais de justiça desse estado (entidade=Tribunal). +// @Produce json +// @Param grupo path string false "Grupo de órgãos" Enums(justica-eleitoral, ministerios-publicos, justica-estadual, justica-do-trabalho, justica-federal, justica-militar, justica-superior, conselhos-de-justica, AC, AL, AP, AM, BA, CE, DF, ES, GO, MA, MT, MS, MG, PA, PB, PR, PE, PI, RJ, RN, RS, RO, RR, SC, SP, SE, TO) +// @Success 200 {object} state "Órgãos do grupo" +// @Failure 400 {object} string "Parâmetro inválido" +// @Failure 404 {object} string "Grupo não encontrado" +// @Router /uiapi/v2/orgao/{grupo} [get] func (h handler) V2GetBasicInfoOfType(c echo.Context) error { groupName := strings.ToLower(c.Param("grupo")) var strAgencies []strModels.Agency @@ -615,15 +615,15 @@ func (h handler) GetGeneralRemunerationFromYear(c echo.Context) error { return c.JSON(http.StatusOK, data) } -// @ID GetGeneralRemunerationFromYear -// @Tags ui_api -// @Description Busca os dados, das remunerações (remuneração base/salário, outras remunerações/benefícios, descontos) e benefícios identificados (rubricas/penduricalhos) de um ano inteiro, agrupados por mês. -// @Produce json -// @Param ano path string true "Ano da remuneração. Ex.: 2018, 2019, 2020..." -// @Success 200 {object} []mensalRemuneration "Requisição bem sucedida." -// @Failure 400 {string} string "Parâmetro ano inválido." -// @Failure 500 {string} string "Erro interno." -// @Router /uiapi/v2/geral/remuneracao/{ano} [get] +// @ID GetGeneralRemunerationFromYear +// @Tags ui_api +// @Description Busca os dados, das remunerações (remuneração base/salário, outras remunerações/benefícios, descontos) e benefícios identificados (rubricas/penduricalhos) de um ano inteiro, agrupados por mês. +// @Produce json +// @Param ano path string true "Ano da remuneração. Ex.: 2018, 2019, 2020..." +// @Success 200 {object} []mensalRemuneration "Requisição bem sucedida." +// @Failure 400 {string} string "Parâmetro ano inválido." +// @Failure 500 {string} string "Erro interno." +// @Router /uiapi/v2/geral/remuneracao/{ano} [get] func (h handler) V2GetGeneralRemunerationFromYear(c echo.Context) error { year, err := strconv.Atoi(c.Param("ano")) if err != nil { @@ -686,13 +686,13 @@ func (h handler) GeneralSummaryHandler(c echo.Context) error { }) } -// @ID GetGeneralSummary -// @Tags ui_api -// @Description Busca e resume os dados das remunerações de todos os anos, trazendo o número de órgão participantes das tetativas de coleta (inclue os órgãos da coleta automatizada, coleta manual e órgãos não coletados, mas que armazenamos alguma informação), número total de meses coletados, data do primeiro e último mês coletado e o valor total de remuneração considerando todos os meses. -// @Produce json -// @Success 200 {object} generalSummary "Requisição bem sucedida." -// @Failure 500 {string} string "Erro interno do servidor." -// @Router /uiapi/v2/geral/resumo [get] +// @ID GetGeneralSummary +// @Tags ui_api +// @Description Busca e resume os dados das remunerações de todos os anos, trazendo o número de órgão participantes das tetativas de coleta (inclue os órgãos da coleta automatizada, coleta manual e órgãos não coletados, mas que armazenamos alguma informação), número total de meses coletados, data do primeiro e último mês coletado e o valor total de remuneração considerando todos os meses. +// @Produce json +// @Success 200 {object} generalSummary "Requisição bem sucedida." +// @Failure 500 {string} string "Erro interno do servidor." +// @Router /uiapi/v2/geral/resumo [get] func (h handler) GetGeneralSummary(c echo.Context) error { agencies, err := h.client.Db.GetAgenciesCount() if err != nil { @@ -728,34 +728,34 @@ func (h handler) GetGeneralSummary(c echo.Context) error { }) } -// @ID SearchByUrl -// @Tags ui_api -// @Description Endpoint de busca avançada para remunerações de servidores públicos -// @Description -// @Description Permite realizar pesquisas detalhadas nas remunerações de servidores públicos com múltiplos filtros flexíveis: -// @Description -// @Description - Filtragem por anos específicos -// @Description - Seleção de meses específicos -// @Description - Pesquisa por órgãos públicos de diferentes esferas -// @Description - Categorias de remuneração -// @Description -// @Description Características principais: -// @Description - Suporta múltiplas seleções em cada filtro -// @Description - Permite combinações complexas de busca -// @Description - Retorna dados consolidados de remuneração dos contracheques por membros -// @Description -// @Description Casos de uso: -// @Description - Análise comparativa de remunerações entre diferentes órgãos -// @Description - Análise análise granular das remunerações por membros dos órgãos -// @Produce json -// @Param anos query string false "Lista de anos a serem pesquisados, separados por virgula. Exemplo: 2018,2019,2020" -// @Param meses query string false "Lista de meses a serem pesquisados, separados por virgula. Exemplo: 1,2,3" -// @Param orgaos query string false "Lista de órgãos a serem pesquisados, separados por virgula. Exemplo: tjal,mpal,mppb" -// @Param categorias query string false "Categorias a serem pesquisadas. Remuneração base (salário), outras remunerações (benefícios) e descontos" Enums(base,outras,descontos) -// @Success 200 {object} searchResponse "Requisição bem-sucedida com dados de remuneração" -// @Failure 400 {string} string "Erro de validação dos parâmetros de busca" -// @Failure 500 {string} string "Erro interno do servidor durante processamento da pesquisa" -// @Router /uiapi/v2/pesquisar [get] +// @ID SearchByUrl +// @Tags ui_api +// @Description Endpoint de busca avançada para remunerações de servidores públicos +// @Description +// @Description Permite realizar pesquisas detalhadas nas remunerações de servidores públicos com múltiplos filtros flexíveis: +// @Description +// @Description - Filtragem por anos específicos +// @Description - Seleção de meses específicos +// @Description - Pesquisa por órgãos públicos de diferentes esferas +// @Description - Categorias de remuneração +// @Description +// @Description Características principais: +// @Description - Suporta múltiplas seleções em cada filtro +// @Description - Permite combinações complexas de busca +// @Description - Retorna dados consolidados de remuneração dos contracheques por membros +// @Description +// @Description Casos de uso: +// @Description - Análise comparativa de remunerações entre diferentes órgãos +// @Description - Análise análise granular das remunerações por membros dos órgãos +// @Produce json +// @Param anos query string false "Lista de anos a serem pesquisados, separados por virgula. Exemplo: 2018,2019,2020" +// @Param meses query string false "Lista de meses a serem pesquisados, separados por virgula. Exemplo: 1,2,3" +// @Param orgaos query string false "Lista de órgãos a serem pesquisados, separados por virgula. Exemplo: tjal,mpal,mppb" +// @Param categorias query string false "Categorias a serem pesquisadas. Remuneração base (salário), outras remunerações (benefícios) e descontos" Enums(base,outras,descontos) +// @Success 200 {object} searchResponse "Requisição bem-sucedida com dados de remuneração" +// @Failure 400 {string} string "Erro de validação dos parâmetros de busca" +// @Failure 500 {string} string "Erro interno do servidor durante processamento da pesquisa" +// @Router /uiapi/v2/pesquisar [get] func (h handler) SearchByUrl(c echo.Context) error { //Pegando os query params years := c.QueryParam("anos") @@ -794,29 +794,29 @@ func (h handler) SearchByUrl(c echo.Context) error { return c.JSON(http.StatusOK, response) } -// @ID DownloadByUrl -// @Tags ui_api -// @Description Baixa um arquivo csv referentes a remunerações a partir de filtros. O arquivo tem um limite de 10 mil linhas. Para cada parâmetro, é possível passar múltiplos valores separados por vírgula. As colunas do arquivo csv são: -// @Description -// @Description - Nome do órgão -// @Description - Mês de referência do contracheque -// @Description - Ano de referência do contracheque -// @Description - Matrícula do membro (identificador único do membro no órgão) -// @Description - Nome do membro -// @Description - Cargo que o membro exerce no órgão -// @Description - Lotação (unidade na qual o membro do órgão desenvolve suas atividades) -// @Description - Categoria do contracheque (base, outras remunerações ou descontos) -// @Description - Detalhamento do contracheque (ex: subsídio, desconto, benefício, etc) -// @Description - Valor do contracheque em reais, não corrigido pela inflação -// @Produce json -// @Param anos query string false "Anos a serem pesquisados, separados por virgula. Exemplo: 2018,2019,2020" -// @Param meses query string false "Meses a serem pesquisados, separados por virgula. Exemplo: 1,2,3" -// @Param orgaos query string false "Orgãos a serem pesquisados, separados por virgula. Exemplo: tjal,mpal,mppb" -// @Param categorias query string false "Categorias a serem pesquisadas. Se nada for informado, todas as categorias serão baixadas" Enums(base,outras,descontos) -// @Success 200 {file} file "Arquivo CSV com os dados." -// @Failure 400 {string} string "Erro de validação dos parâmetros." -// @Failure 500 {string} string "Erro interno do servidor." -// @Router /uiapi/v2/download [get] +// @ID DownloadByUrl +// @Tags ui_api +// @Description Baixa um arquivo csv referentes a remunerações a partir de filtros. O arquivo tem um limite de 10 mil linhas. Para cada parâmetro, é possível passar múltiplos valores separados por vírgula. As colunas do arquivo csv são: +// @Description +// @Description - Nome do órgão +// @Description - Mês de referência do contracheque +// @Description - Ano de referência do contracheque +// @Description - Matrícula do membro (identificador único do membro no órgão) +// @Description - Nome do membro +// @Description - Cargo que o membro exerce no órgão +// @Description - Lotação (unidade na qual o membro do órgão desenvolve suas atividades) +// @Description - Categoria do contracheque (base, outras remunerações ou descontos) +// @Description - Detalhamento do contracheque (ex: subsídio, desconto, benefício, etc) +// @Description - Valor do contracheque em reais, não corrigido pela inflação +// @Produce json +// @Param anos query string false "Anos a serem pesquisados, separados por virgula. Exemplo: 2018,2019,2020" +// @Param meses query string false "Meses a serem pesquisados, separados por virgula. Exemplo: 1,2,3" +// @Param orgaos query string false "Orgãos a serem pesquisados, separados por virgula. Exemplo: tjal,mpal,mppb" +// @Param categorias query string false "Categorias a serem pesquisadas. Se nada for informado, todas as categorias serão baixadas" Enums(base,outras,descontos) +// @Success 200 {file} file "Arquivo CSV com os dados." +// @Failure 400 {string} string "Erro de validação dos parâmetros." +// @Failure 500 {string} string "Erro interno do servidor." +// @Router /uiapi/v2/download [get] func (h handler) DownloadByUrl(c echo.Context) error { //Pegando os query params years := c.QueryParam("anos") @@ -852,21 +852,21 @@ func (h handler) DownloadByUrl(c echo.Context) error { //go:embed readme_content.txt var readmeContent []byte -// @ID DownloadReadme -// @Tags ui_api -// @Description Recupera o arquivo README com informações sobre o conjunto de dados. Permite filtrar o README com base em parâmetros opcionais de ano, mês e órgão -// @Description -// @Description Comportamentos: -// @Description - Se nenhum filtro for aplicado, retorna o README original -// @Description - Com filtro de órgão, gera um README com observações específicas sobre potenciais falhas nos dados -// @Produce text/plain -// @Param ano query string false "Ano para filtragem dos dados" default(2024) -// @Param mes query string false "Mês para filtragem dos dados" default(12) -// @Param orgao query string false "Sigla do órgão para filtragem. Ex.: tjal, mppb, mpdft" default(tjrr) -// @Success 200 {string} string "README.txt com conteúdo detalhado" -// @Failure 400 {string} string "Erro de validação de parâmetros (ano/mês inválidos)" -// @Failure 500 {string} string "Erro interno ao processar o README" -// @Router /uiapi/v2/readme [get] +// @ID DownloadReadme +// @Tags ui_api +// @Description Recupera o arquivo README com informações sobre o conjunto de dados. Permite filtrar o README com base em parâmetros opcionais de ano, mês e órgão +// @Description +// @Description Comportamentos: +// @Description - Se nenhum filtro for aplicado, retorna o README original +// @Description - Com filtro de órgão, gera um README com observações específicas sobre potenciais falhas nos dados +// @Produce text/plain +// @Param ano query string false "Ano para filtragem dos dados" default(2024) +// @Param mes query string false "Mês para filtragem dos dados" default(12) +// @Param orgao query string false "Sigla do órgão para filtragem. Ex.: tjal, mppb, mpdft" default(tjrr) +// @Success 200 {string} string "README.txt com conteúdo detalhado" +// @Failure 400 {string} string "Erro de validação de parâmetros (ano/mês inválidos)" +// @Failure 500 {string} string "Erro interno ao processar o README" +// @Router /uiapi/v2/readme [get] func (h handler) DownloadReadme(c echo.Context) error { originalContent := readmeContent year := c.QueryParam("ano") @@ -929,20 +929,20 @@ func (h handler) DownloadReadme(c echo.Context) error { return nil } -// @ID GetAnnualSummary -// @Tags ui_api -// @Description Retorna os dados de remuneração de todos os anos disponíveis para um órgão específico, incluindo: -// @Description - Remuneração base/salário, outras remunerações/benefícios, descontos e remuneração líquida (salário+benefícios-descontos). Dados brutos, agrupados por mês e per capita -// @Description - Quantidade de meses com dados no determinado ano -// @Description - Quantidade média de membros do órgão naquele ano -// @Description - Resumo dos benefícios identificados (rubricas/penduricalhos) e seus respectivos valores no ano -// @Description - Informações do pacote de dados, URL do pacote de dados para download, seu hash e tamanho do pacote de dados (em bytes) -// @Produce json -// @Param orgao path string true "Nome do orgão" -// @Success 200 {object} []annualSummary "Requisição bem sucedida." -// @Failure 400 {string} string "Parâmetro orgao inválido" -// @Failure 500 {string} string "Algo deu errado ao tentar coletar os dados anuais do orgao" -// @Router /uiapi/v1/orgao/resumo/{orgao} [get] +// @ID GetAnnualSummary +// @Tags ui_api +// @Description Retorna os dados de remuneração de todos os anos disponíveis para um órgão específico, incluindo: +// @Description - Remuneração base/salário, outras remunerações/benefícios, descontos e remuneração líquida (salário+benefícios-descontos). Dados brutos, agrupados por mês e per capita +// @Description - Quantidade de meses com dados no determinado ano +// @Description - Quantidade média de membros do órgão naquele ano +// @Description - Resumo dos benefícios identificados (rubricas/penduricalhos) e seus respectivos valores no ano +// @Description - Informações do pacote de dados, URL do pacote de dados para download, seu hash e tamanho do pacote de dados (em bytes) +// @Produce json +// @Param orgao path string true "Nome do orgão" +// @Success 200 {object} []annualSummary "Requisição bem sucedida." +// @Failure 400 {string} string "Parâmetro orgao inválido" +// @Failure 500 {string} string "Algo deu errado ao tentar coletar os dados anuais do orgao" +// @Router /uiapi/v1/orgao/resumo/{orgao} [get] func (h handler) GetAnnualSummary(c echo.Context) error { agencyName := c.Param("orgao") strAgency, err := h.client.Db.GetAgency(agencyName) @@ -989,7 +989,7 @@ func (h handler) GetAnnualSummary(c echo.Context) error { Hash: s.Package.Hash, Size: s.Package.Size, }, - ItemSummary: itemSummary(s.ItemSummary), + ItemSummary: itemSummary(s.ItemSummary), Inconsistent: s.Inconsistent, }) } @@ -1039,3 +1039,40 @@ func (h handler) getSearchResults(limit int, category string, results []searchDe return searchResults, numRows, nil } } + +// @ID GetAveragePerAgency +// @Tags ui_api +// @Description Busca médias (remuneração base, outras remunerações, descontos e remuneração total) de cada órgão em um ano especificado. +// @Produce json +// @Param ano path int true "Ano para filtrar os dados" +// @Success 200 {array} averagePerAgency "Lista de dados de médias dos órgãos" +// @Failure 400 {string} string "Parâmetro ANO inválido" +// @Failure 500 {string} string "Erro ao buscar dados" +// @Router /uiapi/v2/orgao/media/{ano} [get] +func (h handler) GetAveragePerAgency(c echo.Context) error { + year := c.Param("ano") + yearInt, err := strconv.Atoi(year) + if err != nil { + return c.JSON(http.StatusBadRequest, fmt.Sprintf("Parâmetro ANO inválido: %s.", year)) + } + + // Busca os as médias por membro do banco de dados + data, err := h.client.Db.GetAveragePerAgency(yearInt) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("Erro ao buscar dados: %q", err)) + } + + var avgPerAgency []averagePerAgency + for _, d := range data { + avgPerAgency = append(avgPerAgency, averagePerAgency{ + ID: d.AgencyID, + AveragePerMember: &perCapitaData{ + BaseRemuneration: d.BaseRemuneration, + OtherRemunerations: d.OtherRemunerations, + Discounts: d.Discounts, + Remunerations: d.Remunerations}, + }) + } + + return c.JSON(http.StatusOK, avgPerAgency) +} diff --git a/uiapi/models.go b/uiapi/models.go index 522b967..804971c 100644 --- a/uiapi/models.go +++ b/uiapi/models.go @@ -309,3 +309,8 @@ type perCapitaData struct { Discounts float64 `json:"descontos"` Remunerations float64 `json:"remuneracoes"` } + +type averagePerAgency struct { + ID string `json:"id_orgao"` + AveragePerMember *perCapitaData `json:"media_por_membro"` +} diff --git a/uiapi/uiapi_test.go b/uiapi/uiapi_test.go index c912341..cec9686 100644 --- a/uiapi/uiapi_test.go +++ b/uiapi/uiapi_test.go @@ -1682,3 +1682,147 @@ func agencyMonthlyInfos() []models.AgencyMonthlyInfo { }, } } + +func TestGetAveragePerAgency(t *testing.T) { + tests := getAveragePerAgency{} + t.Run("Test GetAveragePerAgency when data exists", tests.testWhenDataExists) + t.Run("Test GetAveragePerAgency when data does not exist", tests.testWhenDataDoesNotExist) + t.Run("Test GetAveragePerAgency when year is invalid", tests.testWhenYearIsInvalid) +} + +type getAveragePerAgency struct{} + +func (g getAveragePerAgency) testWhenDataExists(t *testing.T) { + mockCtrl := gomock.NewController(t) + dbMock := database.NewMockInterface(mockCtrl) + fsMock := file_storage.NewMockInterface(mockCtrl) + + data := []models.PerCapitaData{ + { + AgencyID: "tjal", + BaseRemuneration: 33173.01, + OtherRemunerations: 9119.56, + Discounts: 10382.61, + Remunerations: 33173.01, + }, + { + AgencyID: "tjpb", + BaseRemuneration: 25000.00, + OtherRemunerations: 5000.00, + Discounts: 8000.00, + Remunerations: 25000.00, + }, + } + dbMock.EXPECT().Connect().Return(nil).Times(1) + dbMock.EXPECT().GetAveragePerAgency(2020).Return(data, nil) + + e := echo.New() + request := httptest.NewRequest( + http.MethodGet, + "/uiapi/v2/orgao/media/:ano", + nil, + ) + recorder := httptest.NewRecorder() + ctx := e.NewContext(request, recorder) + ctx.SetParamNames("ano") + ctx.SetParamValues("2020") + + client, _ := storage.NewClient(dbMock, fsMock) + handler, err := NewHandler(client, nil, nil, "us-east-1", "dadosjusbr_public", loc, []string{}, 100, 100) + if err != nil { + t.Fatal(err) + } + handler.GetAveragePerAgency(ctx) + + expectedCode := http.StatusOK + expectedJson := ` + [ + { + "id_orgao": "tjal", + "media_por_membro": { + "remuneracao_base": 33173.01, + "outras_remuneracoes": 9119.56, + "descontos": 10382.61, + "remuneracoes": 33173.01 + } + }, + { + "id_orgao": "tjpb", + "media_por_membro": { + "remuneracao_base": 25000.00, + "outras_remuneracoes": 5000.00, + "descontos": 8000.00, + "remuneracoes": 25000.00 + } + } + ] + ` + + assert.Equal(t, expectedCode, recorder.Code) + assert.JSONEq(t, expectedJson, recorder.Body.String()) +} + +func (g getAveragePerAgency) testWhenDataDoesNotExist(t *testing.T) { + mockCtrl := gomock.NewController(t) + dbMock := database.NewMockInterface(mockCtrl) + fsMock := file_storage.NewMockInterface(mockCtrl) + + dbMock.EXPECT().Connect().Return(nil).Times(1) + dbMock.EXPECT().GetAveragePerAgency(2020).Return(nil, nil) + + e := echo.New() + request := httptest.NewRequest( + http.MethodGet, + "/uiapi/v2/orgao/media/:ano", + nil, + ) + recorder := httptest.NewRecorder() + ctx := e.NewContext(request, recorder) + ctx.SetParamNames("ano") + ctx.SetParamValues("2020") + + client, _ := storage.NewClient(dbMock, fsMock) + handler, err := NewHandler(client, nil, nil, "us-east-1", "dadosjusbr_public", loc, []string{}, 100, 100) + if err != nil { + t.Fatal(err) + } + handler.GetAveragePerAgency(ctx) + + expectedCode := http.StatusOK + expectedJson := `null` + + assert.Equal(t, expectedCode, recorder.Code) + assert.JSONEq(t, expectedJson, recorder.Body.String()) +} + +func (g getAveragePerAgency) testWhenYearIsInvalid(t *testing.T) { + mockCtrl := gomock.NewController(t) + dbMock := database.NewMockInterface(mockCtrl) + fsMock := file_storage.NewMockInterface(mockCtrl) + + dbMock.EXPECT().Connect().Return(nil).Times(1) + + e := echo.New() + request := httptest.NewRequest( + http.MethodGet, + "/uiapi/v2/orgao/media/:ano", + nil, + ) + recorder := httptest.NewRecorder() + ctx := e.NewContext(request, recorder) + ctx.SetParamNames("ano") + ctx.SetParamValues("2020a") + + client, _ := storage.NewClient(dbMock, fsMock) + handler, err := NewHandler(client, nil, nil, "us-east-1", "dadosjusbr_public", loc, []string{}, 100, 100) + if err != nil { + t.Fatal(err) + } + handler.GetAveragePerAgency(ctx) + + expectedCode := http.StatusBadRequest + expectedJson := `"Parâmetro ANO inválido: 2020a."` + + assert.Equal(t, expectedCode, recorder.Code) + assert.Equal(t, expectedJson, strings.Trim(recorder.Body.String(), "\n")) +}