def obter_fluxo_inicial(self, documento): """ Retorna o fluxo de acordo com a query para pegar o fluxo inicial de uma tramitacao: “SELECT F.* FROM FLUXOS F WHERE F.SITUACAO_ATUAL = 1 AND F.IND_ATIVO = ‘S’ AND F.ID_TIPO_DOC = :ID_TIPO_DOC” :param documento: :return: """ params = { "ID_TIPO_DOC": documento["ID_TIPO_DOC"], "SITUACAO_ATUAL": 1, "IND_ATIVO": "S", } fluxos = self.api.get(self.fluxo_path, params, bypass_no_content_exception=True) if len(fluxos) == 0: raise SIEException("Nao foi possivel obter o fluxo inical para o tipo de documento especificado.") if len(fluxos) > 2: raise SIEException("Tipo de documento possui mais de um fluxo inicial definido. Escolha um manualmente.") return fluxos.first()
def _marcar_tramitacao_atual_entregue(self, documento, fluxo, resolvedor_destino=None): """ Marca a tramitacao atual como entregue, atualiza os campos necessarios e define o fluxo especificado na tramitacao. :param documento: Um dicionario contendo uma entrada da tabela DOCUMENTOS :type documento: dict :param fluxo: Um dicionario referente a uma entrada na tabela FLUXOS :type fluxo: dict :param resolvedor_destino: eh um callable que resolve o destino dado um fluxo que tenha a flag IND_QUERY='S', ou seja, o tipo_destino e id_destino devem ser obtidos atraves de uma query adicional. O retorno deve ser uma tupla (tipo_destino, id_destino). :type resolvedor_destino: callable :raises: SIEException """ try: # Pega a tramitacao atual tramitacao = self.obter_tramitacao_atual(documento) # Espera uma linha de tramitação com status 'T' if self.__is_destino_fluxo_definido_externamente(fluxo): if not resolvedor_destino: raise SIEException("Nao eh possivel tramitar um documento atraves de um fluxo que possui a flag IND_QUERY='S' sem ter especificado uma callable para resolver o destino (id/tipo)") tipo_destino, id_destino = resolvedor_destino(fluxo) fluxo.update({'TIPO_DESTINO': tipo_destino, 'ID_DESTINO': id_destino}) # atualizando a tramitacao tramitacao.update({ "TIPO_DESTINO": fluxo["TIPO_DESTINO"], "ID_DESTINO": fluxo["ID_DESTINO"], "DT_ENVIO": date.today(), "DT_VALIDADE": self.__calcular_data_validade(date.today(), fluxo["NUM_DIAS"]), "DESPACHO": fluxo["TEXTO_DESPACHO"], "DESPACHO_RTF": fluxo["TEXTO_DESPACHO"], "SITUACAO_TRAMIT": SIEDocumentoDAO.TRAMITACAO_SITUACAO_ENTREGUE, "IND_RETORNO_OBRIG": SIEDocumentoDAO.TRAMITACAO_IND_RETORNO_OBRIG_CONFORME_FLUXO, "ID_FLUXO": fluxo["ID_FLUXO"], "DT_ALTERACAO": date.today(), "HR_ALTERACAO": strftime("%H:%M:%S"), "CONCORRENCIA": tramitacao["CONCORRENCIA"] + 1, "ID_USUARIO_INFO": self.usuario["ID_USUARIO"], "DT_DESPACHO": date.today(), "HR_DESPACHO": strftime("%H:%M:%S"), "ID_APLIC_ACAO": fluxo["ID_APLIC_ACAO"] }) self.api.put(self.tramite_path, tramitacao) try: self.atualizar_situacao_documento(documento, fluxo) except APIException as e: raise SIEException("Nao foi possivel atualizar o documento", e) except (APIException, SIEException) as e: raise SIEException("Nao foi possivel tramitar o documento", e)
def reverter_ultimo_numero_processo(self): """ Reverte a geracao do ultimo numero de processo. """ params = {"ID_TIPO_DOC": self.id_tipo_doc, "ANO_TIPO_DOC": self.ano} fields = ["NUM_ULTIMO_DOC"] try: valor_anterior = self.api.get_single_result(self.path, params, fields)["NUM_ULTIMO_DOC"] - 1 # TODO resolver problema de concorrencia try: self.__atualizar_ultimo_numero_tipo_documento(valor_anterior) except Exception as e: raise SIEException("Erro ao reverter geracao de numero de processo.", e) except ValueError as e: raise SIEException("Nao existem registros de numeros de processo para o tipo de documento " + str(self.id_tipo_doc), e)
def __proximo_numero_tipo_documento(self): """ O metodo retorna qual sera o proximo NUM_TIPO_DOC que sera utilizado. Caso ja exista uma entrada nesta tabela para o ANO_TIPO_DOC e ID_TIPO_DOC, retornara o ultimo numero, caso contrario, uma nova entrada sera criada. :rtype: int :raises: SIEException """ params = {"ID_TIPO_DOC": self.id_tipo_doc, "ANO_TIPO_DOC": self.ano} fields = ["NUM_ULTIMO_DOC"] try: numero_novo = self.api.get_single_result(self.path, params, fields)["NUM_ULTIMO_DOC"] + 1 # TODO resolver problema de concorrencia try: self.__atualizar_ultimo_numero_tipo_documento(numero_novo) except Exception as e: raise SIEException("Erro ao atualizar contador numero de processo para o tipo de documento %d" % self.id_tipo_doc, e) except ValueError as e: # caso nao exista uma entrada na tabela, criar uma para comecar a gerir a sequencia de numeros de processo para esse tipo de documento/ano # SIEException("Não existe entrada na tabela de numeros de processo para o tipo de documento %d" % self.id_tipo_doc, e) self.atualizar_indicadores_default() numero_novo = self.criar_novo_numero_tipo_documento() return numero_novo
def registrar_projeto(self, id_projeto): """ Cria o documento e tramita para DPQ. Muda status do projeto tb. :param id_projeto: :return: :rtype: bool """ #verificar se tem classificações classificacoes_projeto = SIEClassifProjetos().get_classificacoes_cnpq(id_projeto) grupos_projeto = SIEClassifProjetos().get_grupos_cnpq(id_projeto) camara_pesquisa = SIEClassifProjetos().get_camara_pesquisa(id_projeto) if not camara_pesquisa or not classificacoes_projeto or not grupos_projeto: raise SIEException("Projeto não cadastrado. Favor informar as classificações na aba anterior.") documento_projeto = self.documento_inicial_padrao() documentoDAO = SIEDocumentoDAO() documento = documentoDAO.criar_documento(documento_projeto) # PASSO 1 # marcando a maneira de lidar com o fluxo caso o destino esteja em uma query (IND_QUERY='S') # resolvedor_destino = lambda fluxo: self.resolve_destino_tramitacao(fluxo, id_projeto) # Era usado anteriormente. Deixando aqui pois pode server para depois. # faz a primeira tramitação fluxo = documentoDAO.obter_fluxo_inicial(documento) documentoDAO.tramitar_documento(documento, fluxo) projeto = { "ID_PROJETO": id_projeto, "ID_DOCUMENTO": documento['ID_DOCUMENTO'], "NUM_PROCESSO": documento['NUM_PROCESSO'] } return self.atualizar_projeto(projeto)
def deletar_candidatos(self, candidatos): try: for candidato in candidatos: params = {"ID_CANDIDATOS_BOLSISTA": candidato["ID_CANDIDATOS_BOLSISTA"]} # Deletar linha do candidato self.api.delete(self.path, params) # plano de estudo relacionado. SIEArquivosProj().deletar_arquivo(candidato["ID_PLANO_ESTUDO"]) except APIException as e: raise SIEException("Não foi possível deletar candidato a bolsista", e) return True
def obter_tramitacao_atual(self, documento): """ Retorna a tramitacao atual (mais recente) do documento. :param documento: Um dicionario contendo uma entrada da tabela DOCUMENTOS :type documento: dict :return: Uma dicionario correspondente a uma entrada da tabela TRAMITACOES :rtype : dict :raises: SIEException """ try: params = { "ID_DOCUMENTO": documento['ID_DOCUMENTO'], "ORDERBY": "SEQUENCIA", "SORT": "DESC" } # Pega a tramitacao atual tramitacao = self.api.get_single_result(self.tramite_path, params) except APIException as e: raise SIEException("Nao foi possivel obter tramitacao", e) return tramitacao
def descricaoDeItem(self, ITEM_TABELA, COD_TABELA): """ Método de conveniência para :type ITEM_TABELA: int :type COD_TABELA: int :param ITEM_TABELA: :param COD_TABELA: :return: """ params = { "ITEM_TABELA": ITEM_TABELA, "COD_TABELA": COD_TABELA, "LMIN": 0, "LMAX": 1 } fields = ["DESCRICAO"] try: return self.api.get(self.path, params, fields, cache_time=self.cacheTime).first()["DESCRICAO"] except NoContentException as e: raise SIEException("Descrição não encontrada.", e)
def _marcar_tramitacao_atual_recebida(self,documento): """ Marca o documento como recebido na tramitacao atual do documento Esse metodo deve ser usado para emular a abertura da tramitacao atraves da caixa postal do SIE. :param documento: Um dicionario contendo uma entrada da tabela DOCUMENTOS :type documento: dict :raises: SIEException """ try: # Pega a tramitacao atual tramitacao = self.obter_tramitacao_atual(documento) tramitacao.update({ "SITUACAO_TRAMIT": SIEDocumentoDAO.TRAMITACAO_SITUACAO_RECEBIDO, "DT_ALTERACAO": date.today(), "HR_ALTERACAO": strftime("%H:%M:%S"), }) self.api.put(self.tramite_path, tramitacao) except (APIException, SIEException) as e: raise SIEException("Nao foi possivel tramitar o documento", e)
def _criar_registro_tramitacao(self,documento): """ Cria um registro novo na tabela de tramitacoes para esse documento. :param documento: Um dicionario contendo uma entrada da tabela DOCUMENTOS :type documento: dict :return: Retorna a linha de tramitacao recem criada :rtype: dict :raises: SIEException """ # pegar a mais recente do documento tramitacao_anterior = self.obter_tramitacao_atual(documento) # so deveriamos criar um registro novo caso a tramitacao anterior estiver no estado SIEDocumentoDAO.TRAMITACAO_SITUACAO_RECEBIDO # essa restricao pode conflitar com dados antigos e incosistentes if tramitacao_anterior["SITUACAO_TRAMIT"] != SIEDocumentoDAO.TRAMITACAO_SITUACAO_RECEBIDO: raise SIEException("Tramitacao anterior ainda nao foi processada") tramitacao_params = { "SEQUENCIA": tramitacao_anterior["SEQUENCIA"] + 1, "ID_DOCUMENTO": documento["ID_DOCUMENTO"], "TIPO_ORIGEM": documento["TIPO_PROPRIETARIO"], "ID_ORIGEM": documento["ID_PROPRIETARIO"], "TIPO_DESTINO": documento["TIPO_PROPRIETARIO"], "ID_DESTINO": documento["ID_PROPRIETARIO"], "DT_ENVIO": date.today(), "SITUACAO_TRAMIT": SIEDocumentoDAO.TRAMITACAO_SITUACAO_AGUARDANDO, "IND_RETORNO_OBRIG": SIEDocumentoDAO.TRAMITACAO_IND_RETORNO_OBRIG_NAO, "DT_ALTERACAO": date.today(), "HR_ALTERACAO": strftime("%H:%M:%S"), "PRIORIDADE_TAB": 5101, "PRIORIDADE_ITEM": SIEDocumentoDAO.TRAMITACAO_PRIORIDADE_NORMAL } id_tramitacao = self.api.post(self.tramite_path, tramitacao_params).insertId tramitacao = self.api.get_single_result(self.tramite_path, {"ID_TRAMITACAO": id_tramitacao}) # pega uma instancia nova do banco (por seguranca) return tramitacao
def itemsDeCodigo(self, COD_TABELA): """ Dado um COD_TABELA, a função retornará uma lista de dicionários de valores possíveis de ITEM_TABELA e sua DESCRICAO :param COD_TABELA: Identificador de único de um domínio de valores de uma tabela :raise AttributeError: Uma exception é disparada caso nenhum item seja encontrado para o COD_TABELA :rtype : list :return: Uma lista de dicionários contendo as chaves `ITEM_TABELA` e `COD_TABELA` """ params = { "COD_TABELA": COD_TABELA, "LMIN": 0, "LMAX": 99999, "IND_ATIVO": self.COD_IND_ATIVO } fields = ["ITEM_TABELA", "DESCRICAO"] try: items = self.api.get(self.path, params, fields, cache_time=self.cacheTime).content # Primeiro item de uma de ITEMS de uma TABELA é sempre a descrição do conteúdo return items[1:] except NoContentException as e: raise SIEException("Nenhum item encontreado para este código.", e)
def gerar_numero_processo(self): """ Gera o proximo numero de processo a ser usado, formado de acordo com a mascara do tipo de documento. :rtype: str :return: Retorna o NUM_PROCESSO gerado a partir da logica de negocio :raise: SIEException """ try: try: mascara = SIETiposDocumentosDAO().obter_mascara(self.id_tipo_doc) prox_numero = self.__proximo_numero_tipo_documento() except APIException as e: raise SIEException("Erro obter mascara do tipo documento " + str(self.id_tipo_doc), e) if mascara == "pNNNN/AAAA": # TODO usar o parser de mascara ao inves dessa gambi numero = self.__gera_numero_processo_projeto(prox_numero, "P") elif mascara == "eNNNN/AAAA": # TODO usar o parser de mascara ao inves dessa gambi numero = self.__gera_numero_processo_projeto(prox_numero, "e") elif mascara == "xNNNN/AAAA": # TODO usar o parser de mascara ao inves dessa gambi numero = self.__gera_numero_processo_projeto(prox_numero, "x") elif mascara == "dNNNN/AAAA": # TODO usar o parser de mascara ao inves dessa gambi numero = self.__gera_numero_processo_projeto(prox_numero, "d") elif mascara == "NNNNNN/AAAA": # TODO usar um parser de mascar em vez dessa gambi numero = self.__gera_numero_processo_avaliacao_projeto(prox_numero) else: # interpretar a mascara # TODO Criar parser para mascara para entender como gerar o numero do processo de modo generico raise NotImplementedError return numero except Exception as e: raise e#raise SIEException("Erro ao gerar numero de processo.", e)
def enviar_relatorio_docente(self, relatorio, params_projeto): documento_dao = SIEDocumentoDAO() avaliacao = SIEAvaliacaoProjsPesquisaDAO().get_avaliacao(params_projeto['ANO_REF_AVAL'],relatorio.id_projeto,params_projeto["PERIODO_REF_TAB"],params_projeto["PERIODO_REF_ITEM"]) if avaliacao: avaliacao_com_professor = SIEAvaliacaoProjsPesquisaDAO().is_avaliacao_com_professor(avaliacao) if not avaliacao_com_professor: raise SIEException("Já há avaliação cadastrada para este projeto neste período de avaliação. Caso queira enviar outra avaliação, entre em contato com a DPq.") else: #Salva relatorio arquivo_salvo = SIEArquivosProj().salvar_arquivo(nome_arquivo=relatorio.filename, arquivo=relatorio.arquivo, id_projeto=relatorio.id_projeto, tipo_arquivo=SIEArquivosProj.ITEM_TIPO_ARQUIVO_RELATORIO_DOCENTE) # atualizar ref tabela de arquivos com id da avaliacao SIEArquivosProj().atualizar_arquivo(arquivo_salvo["ID_ARQUIVO_PROJ"], {"ID_AVALIACAO_PROJ": avaliacao["ID_AVALIACAO_PROJ"]}) #obtem estado atual documento = documento_dao.obter_documento(avaliacao["ID_DOCUMENTO"]) tramitacao_atual = documento_dao.obter_tramitacao_atual(documento) #recebe documento se necessario if tramitacao_atual["SITUACAO_TRAMIT"]==SIEDocumentoDAO.TRAMITACAO_SITUACAO_ENTREGUE: documento_dao.receber_documento(documento) elif tramitacao_atual["SITUACAO_TRAMIT"]==SIEDocumentoDAO.TRAMITACAO_SITUACAO_AGUARDANDO: #Só tramitar pass else: #Shouldn't fall here. raise NotImplementedError # tramita para DPq de novo. fluxo = documento_dao.obter_fluxo_inicial(documento) #TODO É o fluxo inicial? Me parece ser! Senão seria o último. documento_dao.tramitar_documento(documento, fluxo) else: #Salva relatorio arquivo_salvo = SIEArquivosProj().salvar_arquivo(nome_arquivo=relatorio.filename, arquivo=relatorio.arquivo, id_projeto=relatorio.id_projeto, tipo_arquivo=SIEArquivosProj.ITEM_TIPO_ARQUIVO_RELATORIO_DOCENTE) #cria documento avaliacao documento_avaliacao = SIEAvaliacaoProjsPesquisaDAO().documento_inicial_padrao() projeto = self.get_projeto(relatorio.id_projeto) documento_avaliacao.update({ "RESUMO_ASSUNTO": "Projeto n"+u"\u00BA " + projeto['NUM_PROCESSO'].strip() # Parece ser. }) documento = documento_dao.criar_documento(documento_avaliacao) # PASSO 1 # cria avaliacao para o arquivo avaliacao = SIEAvaliacaoProjsPesquisaDAO().criar_avaliacao(projeto,documento,params_projeto,data_prorrogacao=relatorio.nova_data_conclusao,obs=relatorio.obs) # atualizar ref tabela de arquivos com id da avaliacao SIEArquivosProj().atualizar_arquivo(arquivo_salvo["ID_ARQUIVO_PROJ"], {"ID_AVALIACAO_PROJ": avaliacao["ID_AVALIACAO_PROJ"]}) # tramita para a câmara fluxo = documento_dao.obter_fluxo_inicial(documento) documento_dao.tramitar_documento(documento, fluxo) #atualizar projeto com avaliacao_item pendente. self.atualizar_projeto({ "ID_PROJETO":relatorio.id_projeto, "AVALIACAO_ITEM": SIEProjetosPesquisa.ITEM_AVALIACAO_PROJETOS_INSTITUICAO_PENDENTE_AVALIACAO })