import pandas as pd
import requests
import json
import numpy as np

TOKEN = '198f959a5f39a1c441c7c863423264'
base_url = "https://gatewayapi.prodam.sp.gov.br:443/financas/orcamento/sof/v2.1.0"
headers={'Authorization' : str('Bearer ' + TOKEN)}

"""
Explanation: Explorando os contratos da cidade de São Paulo
Na primeira parte deste tutorial, procurei mostrar como:
1. Fazer o cadastro na API do SOF
2. Acessar os registros de empenhos (a execução orçamentária)
3. Utilizar o Pandas para explorar algumas análises
4. Fazer download da base em CSV
Neste segundo tutorial, vamos focar em outra consulta disponível na mesma API: os contratos. 
A Prefeitura de São Paulo ainda não dispõe de um sistema centralizado para gestão de contratos (existe um em implementação). 
A boa notícia é que, com relação a contratos, se pode considerar uma das cidades mais transparentes do Brasil por ser uma das poucas a disponibilizar os termos de seus contratos e convênios na íntegra, desde 2014, nesta página do Portal da Transparência. Com o Marco Regulatório da Sociedade Civil, vigente a partir deste ano, também começam a aparecer por lá os Termos de Cooperação (sem transferência de recursos) que antes não eram publicados.Também as doações começaram a aparecer aí. 
A má notícia é que nessa base do Portal você consegue extrair as informações publicadas em Diário Oficial, mas pode haver inconsistências (geradas por erros de publicação no D.O.). Às vezes há duplicidade, republicação, valores equivocados (pois são digitados manualmente na hora de publicar).   
Por isso, podemos considerar que o registro mais confiável que há sobre a execução dos contratos é o do próprio sistema de Execução Orçamentária (o SOF), uma vez que é necessário cadastrar os contratos para realizar os pagamentos. E é daí a relevância desta API.
Importante!
A diferença com relação ao que está no Portal da Transparência é que os contratos não são imediatamente cadastrados no SOF (ele passa a existir no sistema apenas quando é gerado empenho vinculado a ele). Por isso, se quiser tratar no universo inteiro de contratos e não apenas da execução orçamentária, recomendo o 'double check' com a base do Portal da Transparência.
Passo 1. Consulta à API
Seguiremos os passos detalhados no tutorial anterior para acessar essa consulta na API e utilizar o Pandas para montar um DataFrame.
End of explanation
"""


url_orgaos = '{base_url}/consultarOrgaos?anoExercicio=2017'.format(base_url=base_url)

request_orgaos = requests.get(url_orgaos,
                                headers=headers,
                                verify=True).json()

df_orgaos = pd.DataFrame(request_orgaos['lstOrgaos'])

df_orgaos

"""
Explanation: Um parêntesis! Como saber qual é o código do órgão que quero pesquisar?
Na consulta anterior, eu indiquei que o Código da Educação no Orçamento, por exemplo, é 16; o Fundo Municipal de Saúde, 84. Quem mexe com o orçamento, acaba se acostumando com os números. Mas como saber o código de todas as secretarias e empresas municipais? Existe uma consulta específica para isso na API, que você pode fazer lá no próprio console. Mas vamos trazer essa tabela para cá, para facilitar:
End of explanation
"""


url_contratos = '{base_url}/consultaContrato?anoContrato=2017&codOrgao=27'.format(base_url=base_url)

request_contratos = requests.get(url_contratos,
                                headers=headers,
                                verify=True).json()

number_of_pages = request_contratos['metadados']['qtdPaginas']

todos_contratos = []
todos_contratos = todos_contratos + request_contratos['lstContratos']
if number_of_pages>1:
    for p in range(2, number_of_pages+1):
        request_contratos = requests.get(url_contratos + pagination.format(PAGE=p), headers=headers, verify=True).json()
        todos_contratos = todos_contratos + request_contratos['lstContratos']

"""
Explanation: Atenção para uma distinção conceitual importante!

ÓRGÃO = Administração Direta (Prefeituras Regionais, Secretarias)
EMPRESA = Administração Indireta (Fundações, Empresas Públicas)

Os campos na consulta da API são diferentes. Então se você inserir o Código da Prodam (uma empresa pública) no Campo Órgão, por exemplo, a consulta vai retornar 0 Registros.  
Pronto, aí temos a lista completa. Fecha parêntesis!
Seguindo, vamos fazer a consulta dos contratos da Secretaria do Verde e Meio Ambiente -- Órgão 27, conforme a lista acima.
End of explanation
"""


df_contratos = pd.DataFrame(todos_contratos)

"""
Explanation: Passo 2. Mãos ao Pandas!
End of explanation
"""


df_contratos.tail()

"""
Explanation: Vamos checar como ficou nossa base de dados de contratos, mostrando os últimos 5 registros:
End of explanation
"""


list(df_contratos)

df_contratos.to_csv('contratos_verde.csv')

"""
Explanation: São muitas as colunas dessa consulta (a visualização acima omite algumas). Vamos checar quais são:
End of explanation
"""


df_contratos.drop('txtRazaoSocial', axis=1, inplace=True)

"""
Explanation: Vamos remover o txtRazaoSocial, para não nos atrapalhar mais tarde (vamos obter o dado de outro local). Esta consulta não retorna o nome das empresas contratadas, mas "PREFEITURA DE SÃO PAULO" para todos os valores -- provavelmente um erro da API.
End of explanation
"""


url_empenho = '{base_url}/consultaEmpenhos?anoEmpenho=2017&mesEmpenho=08&codOrgao=27'.format(base_url=base_url)
num_contrato = '&codContrato={CONTRATO}'

lista_contratos = list(df_contratos['codContrato'])
len(lista_contratos)

request_empenhos = requests.get(url_empenho,
                                headers=headers,
                                verify=True).json()

def add_codigo_contrato(empenhos, cod_contrato):
    """""
    Adiciona Código de Contrato no dict de cada empenho consultado. 
    """""
    for item in empenhos:
        item.update({'codContrato': cod_contrato})
    return empenhos

todos_empenhos = []

todos_empenhos = todos_empenhos + request_empenhos['lstEmpenhos']

for n in lista_contratos:
    response = requests.get(url_empenho + num_contrato.format(CONTRATO=n), headers=headers, verify=True).json()
    empenhos_c_cod = add_codigo_contrato(response['lstEmpenhos'], n)
    todos_empenhos = todos_empenhos + empenhos_c_cod

df_empenhos_c_contratos = pd.DataFrame(todos_empenhos)

"""
Explanation: Cruzando as bases
Infelizmente, a consulta não vem "pronta". Vamos precisar cruzar com a base de empenhos do primeiro tutorial para conseguir, por exemplo, saber quais são os credores POR CONTRATO. A imagem abaixo foi exibida durante o lançamento da API, no Café Hacker da Controladoria Geral do Município e da Secretaria Municipal da Fazenda, e explica como as consultas se relacionam (o 'Simplificada' é por conta deles, hehe): 

O Código de Contrato é um parâmetro facultativo da consulta de empenhos, mas não vem no retorno de dados (outro possível furo da API, que vamos alertar aos desenvolvedores para tentar corrigir). O que isso significa? Que precisaríamos consultar um a um para obter todos os contratos na lista de empenhos! Felizmente, a programação tá aí pra isso. Vamos criar uma estrutura de repetição semelhante à que fizemos para a paginação:
End of explanation
"""


df_empenhos_c_contratos.tail()

"""
Explanation: Agora já temos o DataFrame que junta todos Empenhos do Verde de 2017 com as informações de Contrato, deixando a base mais rica -- e corrigindo essa falha da falta de Razão Social e CNPJ na consulta de contratos!
End of explanation
"""


df_empenhos_c_contratos = df_empenhos_c_contratos.dropna(axis=0).reset_index(drop=True)

df_empenhos_c_contratos['codContrato'] = df_empenhos_c_contratos.loc[:,'codContrato'].astype(int)

"""
Explanation: A tabela acima vai ter muitos valores "Nan" para codContrato -- pois há 493 empenhos e apenas 80 contratos. Como o interesse agora é só nos contratos, vamos retirar esses casos e montar um novo DataFrame que contém apenas contratos com algum empenho relacionado:
End of explanation
"""


cols_to_use = df_empenhos_c_contratos.columns.difference(df_contratos.columns)

df_contratos_empenhados = df_contratos.merge(df_empenhos_c_contratos[cols_to_use], left_index=True, right_index=True, how='outer')

"""
Explanation: Agora temos duas bases de dados para trabalhar:
* df_contratos = Primeira base que extraímos, contém todos os contratos (sem Razão Social ou CNPJ, por limitação da API)
* df_empenhos_c_contratos = Base que contém todos os empenhos com código de contrato, depois do cruzamento que fizemos
Ambas têm várias colunas em comum. Então, antes de juntá-las, vamos apenas retirar as colunas únicas nas duas, com o método "difference":
End of explanation
"""


df_contratos_empenhados.columns

top20 = df_contratos_empenhados[['txtDescricaoModalidade',
                                 'txtObjetoContrato',
                                 'txtRazaoSocial',
                                 'numCpfCnpj',
                                 'valPrincipal']]

#top20.sort_values(['valPrincipal'], ascending=False)

"""
Explanation: 'Top 10' Contratos de 2017
Agora com a lista de todos os contratos do ano, vamos montar uma tabela e ordenar os dados pelo Valor Principal do Contrato. No Manual da API, aprende-se que esse campo 'valPrincipal'significa o "Valor do contrato sem ocorrência de reajustamentos, ou aditamentos".
End of explanation
"""


tipo_licitacao = df_contratos_Verde[]

"""
Explanation: Modalidades de Contratação
Várias são as análises possíveis com os campos acima. Vamos ver quantas as contratações a SMVMA fez em 2017, por tipo de licitação:
End of explanation
"""


