class Tcm::Lote < ApplicationRecord
	has_paper_trail
	include TradutorConcern
	include SimConcern
	include Tcm::ValidarArquivoConcern

	attr_accessor :lote, :gerando_lote_individual

	belongs_to :orcamento, required: true
	has_many :arquivos, dependent: :destroy
	has_many :erros_do_arquivo, class_name: "Tcm::ErroDoArquivo", dependent: :destroy

	attr_default :situacao, :pendente

	# validates_presence_of :orcamento_id
	# validates_presence_of :tipo, if: Proc.new { (gerando_lote_individual.nil? && new_record?) || (persisted? && tipo.present?) }
	# validates_presence_of :mes_de_referencia, :tipo_de_poder, on: :create

	after_create :gera_todos_os_arquivos_em_segundo_plano, if: Proc.new { gerando_lote_individual.nil? && contexto_atual.present?}
	#after_create :gera_lote_individual, if: Proc.new { gerando_lote_individual.present? }

  accepts_nested_attributes_for :arquivos, reject_if: :all_blank, allow_destroy: true
  validates_associated :arquivos

	validate :existem_dados_do_orcamento_a_serem_enviados, :on => :create
	validate :existem_dados_da_licitacao_a_serem_enviados, :on => :create
	#validate :deve_existir_responsaveis_para_gerar_o_lote, :on => :create

	# validate :sim_deve_ser_unico, if: proc { mes_de_referencia.present? && tipo.present? }, on: :create
	#validate :valida_se_possui_balancete_pcasp_gerado
	#validate :horario_de_geracao_permitido, if: Proc.new { gerando_lote_individual.nil?}
	#validate :criticas_bloqueadoras, :on => :create

	enum tipo: {
		orcamento: 1,
		licitacao: 2,
		contabilidade: 3,
		patrimonio: 4,
		aprovacao_loa: 5,
		todos: 99
	}

	enum situacao: {
		"pendente": 99,
		"gerando": 0,
		"gerado": 1,
		"cancelado": 8,
		"finalizado": 9
	}

	# o enum foi feito assim para ficar no mesmo padrão do tipo do poder do Usuario
	enum tipo_de_poder: {
    executivo: 2,
    legislativo: 3
	}

	enum mes_de_referencia: {
		janeiro: 1,
		fevereiro: 2,
		marco: 3,
		abril: 4,
		maio: 5,
		junho: 6,
		julho: 7,
		agosto: 8,
		setembro: 9,
		outubro: 10,
		novembro: 11,
		dezembro: 12
	}

	def pode_gerar_sem_bloqueio_de_sistema?
		self.orcamento? || self.licitacao? || (self.contabilidade? && self.legislativo?)
	end

	def lote_processado_ou_enviado?
		self.gerando? || self.gerado? || self.finalizado?
	end

	def arquivo_de_porte_grande?
		(self.contabilidade? == self.executivo?) || self.patrimonio?
	end

	def mes_bloqueado?
		mes = Contabilidade::BloqueioMensalDoPcasp.find_by(mes_referencia: Tcm::Lote.mes_de_referencias[mes_de_referencia].to_i, orcamento_id: self.orcamento.id, bloqueado: true)
		return mes.present?
	end

	def arquivos_processados_igual_a_arquivos?
		self.arquivos.size == self.arquivos.where(situacao: :processado).size
	end

	def metodos_que_geram_sim
		hash_metodos = {}
		metodos = Tcm::Lote.instance_methods.map { |i| i.to_s }.select{ |i| i.include?('gera') }

		metodos.each do |metodo|
			metodo_filtrado = metodo.gsub('gerar_', '').gsub('gera_', '').tr('_', ' ')
			hash_metodos[metodo] = metodo_filtrado.capitalize unless metodo_filtrado.include?('gera_')
		end

		hash_metodos
	end

	def gera_lote_individual
		send(lote)
		self.update_column(:situacao, 1)
	end

	def poder_associado
		Base::TipoDeUnidadeAdministrativa.poderes_associados[tipo_de_poder]
	end

	def data_referencia
		("01/" << "#{Tcm::Lote.mes_de_referencias[mes_de_referencia].to_s}/" << orcamento.exercicio.to_s).to_date
	end

	def mes_de_geracao
		Tcm::Lote.mes_de_referencias[mes_de_referencia].digitos(2) unless mes_de_referencia.blank?
	end

	def exercicio_e_mes_de_geracao
		exercicio_e_mes = orcamento.exercicio.to_s
		exercicio_e_mes << self.mes_de_geracao unless self.mes_de_geracao.nil?
	end

	def exercicio_e_nome_do_mes
		exercicio_e_mes = orcamento.exercicio.to_s
		exercicio_e_mes << " / " << Date::MONTHNAMES[Tcm::Lote.mes_de_referencias[self.mes_de_referencia]] unless self.mes_de_referencia.blank?
	end

	def salva_ou_deleta_arquivo(arquivo)
		arquivo.save
	end

	def limpa_arquivo_individual(arquivo)
		exceto = ["Loa::BalanceteDeReceitaOrcamentaria", "Contabilidade::BalanceteDeDespesaExtraOrcamentaria", "Loa::BalanceteDeDespesaOrcamentaria", "Pagamento::Cheque", "Pagamento::Folha", "Pagamento::Liquidacao", "Gestor::Final", "OrdenadorDeDespesa::Final", "BemPatrimonial::PorUnidade", "BemPatrimonial::PorEmpenho", "MovimentacaoFinanceiraDoBem::ContasRedutoras", "MembroDoConselhoDoRpps::Final"]

		if arquivo.classe.present? && !exceto.include?(arquivo.classe)
			arquivo.classe.split(";").each do |classe|
				if !exceto.include?(classe)
					classe.constantize.where(arquivo_id: arquivo.id).all.each do |objeto|
						objeto.update_column(:arquivo_id, nil)
					end
				end
			end
		end

		if arquivo.classe.present? && (arquivo.classe == "Contabilidade::DotacaoOrigem" || arquivo.classe == "Contabilidade::DotacaoDestino")
			arquivo.classe.split(";").each do |classe|
				classe.constantize.where(arquivo_id_rtt: arquivo.id).all.each do |objeto|
					objeto.update_column(:arquivo_id_rtt, nil)
				end
			end
		end

		if arquivo.classe.present? && arquivo.classe == "Pagamento::Cheque"
			arquivo.classe.split(";").each do |classe|
				Contabilidade::Pagamento.where(arquivo_de_cheque_id: arquivo.id).all.each do |objeto|
					objeto.update_column(:arquivo_de_cheque_id, nil)
				end
			end
		end

		if arquivo.classe.present? && arquivo.classe == "Gestor::Final"
			arquivo.classe.split(";").each do |classe|
				Loa::Gestor.where(arquivo_final_id: arquivo.id).all.each do |objeto|
					objeto.update_column(:arquivo_final_id, nil)
				end
			end
		end

		if arquivo.classe.present? && arquivo.classe == "Pagamento::Liquidacao"
			arquivo.classe.split(";").each do |classe|
				Contabilidade::Pagamento.where(arquivo_liquidacao_id: arquivo.id).all.each do |objeto|
					objeto.update_column(:arquivo_liquidacao_id, nil)
				end
			end
		end

		if arquivo.classe.present? && arquivo.classe == "OrdenadorDeDespesa::Final"
			arquivo.classe.split(";").each do |classe|
				Loa::OrdenadorDeDespesa.where(arquivo_final_id: arquivo.id).all.each do |objeto|
					objeto.update_column(:arquivo_final_id, nil)
				end
			end
		end

		if arquivo.classe.present? && arquivo.classe.include?("MembroDoConselhoDoRpps::Final")
			arquivo.classe.split(";").each do |classe|
				Contabilidade::MembroDoConselhoDoRpps.where(arquivo_final_id: arquivo.id).all.each do |objeto|
					objeto.update_column(:arquivo_final_id, nil)
				end
			end
		end

		if arquivo.classe.present? && arquivo.classe == "Pagamento::Folha"
			arquivo.classe.split(";").each do |classe|
				Contabilidade::Pagamento.where(arquivo_de_folha_id: arquivo.id).all.each do |objeto|
					objeto.update_column(:arquivo_de_folha_id, nil)
				end
			end
		end

		if arquivo.classe.present? && arquivo.classe == "BemPatrimonial::PorUnidade"
			arquivo.classe.split(";").each do |classe|
				Patrimonio::BemPatrimonial.where(arquivo_por_unidade_id: arquivo.id).all.each do |objeto|
					objeto.update_column(:arquivo_por_unidade_id, nil)
				end
			end
		end

		if arquivo.classe.present? && arquivo.classe == "BemPatrimonial::PorEmpenho"
			arquivo.classe.split(";").each do |classe|
				Patrimonio::BemPatrimonial.where(arquivo_por_empenho_id: arquivo.id).all.each do |objeto|
					objeto.update_column(:arquivo_por_empenho_id, nil)
				end
			end
		end

		if arquivo.classe.present? && arquivo.classe == "MovimentacaoFinanceiraDoBem::ContasRedutoras"
			arquivo.classe.split(";").each do |classe|
				Patrimonio::MovimentacaoFinanceiraDoBem.where(arquivo_contas_id: arquivo.id).all.each do |objeto|
					objeto.update_column(:arquivo_contas_id, nil)
				end
			end
		end

		if arquivo.classe.present? && arquivo.classe == "Loa::BalanceteDeDespesaOrcamentaria"
			Loa::BalanceteDeDespesaOrcamentaria.where(ano_referencia: arquivo.lote.orcamento.exercicio, mes_referencia: arquivo.lote.mes_de_referencia, tipo_de_poder: self.tipo_de_poder).delete_all
		end

		Licitacao::ConfiguracaoSimDoProjeto.where(arquivo_id: arquivo.id).each do |configuracao_sim|
			configuracao_sim.update_column(:arquivo_id, nil)
		end

		arquivo.linhas.each do |linha|
			linha.update_column(:arquivo_id, nil)
		end
	end

	def limpa_arquivos
		self.arquivos.each do |arquivo|
			self.limpa_arquivo_individual(arquivo)
		end
	end

	def gerar_arquivo_vazio(nome, sigla)
		nome_do_arquivo = nome + exercicio_e_mes_de_geracao + sigla
		arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")
	end

	# ORÇAMENTO
	def gera_todos_os_arquivos_do_orcamento
		if self.tipo && (self.orcamento? || self.aprovacao_loa?) && orcamento.present? && self.executivo?

			self.gerar_arquivo_vazio("PA", ".ORC")
			self.gerar_arquivo_vazio("RE", ".ORC")
			self.gerar_arquivo_vazio("DE", ".ORC")
			self.gerar_arquivo_vazio("EP", ".ORC")
			self.gerar_arquivo_vazio("OR", ".BAS")
			self.gerar_arquivo_vazio("UO", ".BAS")
			if self.mes_de_geracao == "01"
				self.gerar_arquivo_vazio("DO", ".ORC")
				self.gerar_arquivo_vazio("PG", ".ORC")
			end

			# puts "Gerando Todos os Arquivos Orçamentarios"
			# @@erro_lote = nil
			# metodos = [
			# 	:gera_arquivo_de_orcamento_das_despesas_por_projetos,
			# 	:gera_arquivo_de_orcamentos_das_receitas,
			# 	:gera_arquivo_de_orcamentos_da_despesa_e_elementos_da_despesa,
			# 	:gera_arquivo_de_orgaos,
			# 	:gerar_arquivo_de_unidades_orcamentarias
			# ]

			# if self.mes_de_geracao == "01"
			# 	metodos.concat([
			# 		:gera_arquivo_de_orcamento,
			# 		:gera_arquivo_de_programas_de_governo
			# 	])
			# end

			# metodos.uniq.each do |metodo|
			# 	ActiveRecord::Base.transaction do
			# 		begin
			# 			self.send(metodo) if self.respond_to?(metodo)
			# 		rescue => e
			# 			@@erro_lote = @@erro_lote.present? ? @@erro_lote : Tcm::ErrosDoLote.create(tipo: self.tipo, orcamento_id: self.orcamento_id, mes_de_referencia: mes_de_referencia, tipo_de_poder: self.tipo_de_poder, situacao: 2)
			# 		end
			# 	end
			# end
			# update_column(:situacao, 1) unless todos?
		end
	end

	# LICITAÇÃO
	def gera_todos_os_arquivos_da_licitacao
		if self.tipo && (self.licitacao? || self.todos?) && orcamento.present?
			self.gerar_arquivo_vazio("LI", ".LCO")
			self.gerar_arquivo_vazio("PE", ".LCO")
			self.gerar_arquivo_vazio("CL", ".LCO")
			self.gerar_arquivo_vazio("MC", ".LCO")
			self.gerar_arquivo_vazio("LT", ".LCO")
			self.gerar_arquivo_vazio("TL", ".LCO")
			self.gerar_arquivo_vazio("DL", ".LCO")
			self.gerar_arquivo_vazio("CO", ".LCO")
			self.gerar_arquivo_vazio("CT", ".LCO")
			self.gerar_arquivo_vazio("PC", ".OSC")
			self.gerar_arquivo_vazio("PP", ".OSC")
			self.gerar_arquivo_vazio("CC", ".OSC")
			self.gerar_arquivo_vazio("MS", ".OSC")
			self.gerar_arquivo_vazio("OC", ".OSC")
			self.gerar_arquivo_vazio("DC", ".OSC")
			self.gerar_arquivo_vazio("PS", ".OSC")
			self.gerar_arquivo_vazio("PD", ".OSC")

			# puts "Gerando Todos os Arquivos Licitação"
			# @@erro_lote = nil
			# metodos = [
			# 	:gera_arquivo_processos,
			# 	:gera_arquivo_publicacoes_de_processos,
			# 	:gera_arquivo_comissoes,
			# 	:gera_arquivo_membros_das_comissoes,
			# 	:gera_arquivo_licitantes,
			# 	:gera_arquivo_itens_do_processo,
			# 	:gera_arquivo_dotacoes_dos_processos,
			# 	:gera_arquivo_contratos_e_aditivos,
			# 	:gera_arquivo_contratados,
			# 	:gera_arquivo_processos_parcerias,
			# 	:gera_arquivo_publicacoes_de_processos_parcerias,
			# 	:gera_arquivo_comissoes_parcerias,
			# 	:gera_arquivo_membros_das_comissoes_parcerias,
			# 	:gera_arquivo_licitantes_parcerias,
			# 	:gera_arquivo_dotacoes_dos_processos_parcerias,
			# 	:gera_arquivo_contratos_parcerias
			# ]

			# metodos.uniq.each do |metodo|
			# 	ActiveRecord::Base.transaction do
			# 		begin
			# 			self.send(metodo) if self.respond_to?(metodo)
			# 		rescue => e
			# 			@@erro_lote = @@erro_lote.present? ? @@erro_lote : Tcm::ErrosDoLote.create(tipo: self.tipo, orcamento_id: self.orcamento_id, mes_de_referencia: mes_de_referencia, tipo_de_poder: self.tipo_de_poder, situacao: 2)
			# 		end
			# 	end
			# end
			# update_column(:situacao, 1) unless todos?
		end
	end

	# CONTABILIDADE
	def gera_todos_os_arquivos_da_contabilidade
		if tipo && (contabilidade? || todos?) && orcamento.present?
			self.gerar_arquivo_vazio("TR", ".DCR")
			self.gerar_arquivo_vazio("TX", ".DCR")
			self.gerar_arquivo_vazio("AT", ".DCR")
			self.gerar_arquivo_vazio("AX", ".DCR")
			self.gerar_arquivo_vazio("NE", ".DCD")
			self.gerar_arquivo_vazio("AE", ".DCD")
			self.gerar_arquivo_vazio("MO", ".OSE")
			self.gerar_arquivo_vazio("LQ", ".DCD")
			self.gerar_arquivo_vazio("NF", ".DCD")
			self.gerar_arquivo_vazio("IF", ".DCD")
			self.gerar_arquivo_vazio("PL", ".DCD")
			self.gerar_arquivo_vazio("NP", ".DCD")
			self.gerar_arquivo_vazio("PF", ".DCD")
			self.gerar_arquivo_vazio("CP", ".DCD")
			self.gerar_arquivo_vazio("DP", ".DCD")
			self.gerar_arquivo_vazio("EL", ".DCD")
			self.gerar_arquivo_vazio("EG", ".DCD")
			self.gerar_arquivo_vazio("XD", ".DCD")
			self.gerar_arquivo_vazio("XE", ".DCD")
			self.gerar_arquivo_vazio("CA", ".CRD")
			self.gerar_arquivo_vazio("FA", ".CRD")
			self.gerar_arquivo_vazio("RT", ".CRD")
			self.gerar_arquivo_vazio("DT", ".CRD")
			self.gerar_arquivo_vazio("MF", ".CRD")
			self.gerar_arquivo_vazio("TF", ".OUT")
			self.gerar_arquivo_vazio("DA", ".OUT")
			self.gerar_arquivo_vazio("OS", ".OSE")
			self.gerar_arquivo_vazio("SO", ".OSE")
			self.gerar_arquivo_vazio("CB", ".BAS")
			self.gerar_arquivo_vazio("XC", ".BAS")
			self.gerar_arquivo_vazio("RC", ".CTR")
			self.gerar_arquivo_vazio("EF", ".DCD")
			self.gerar_arquivo_vazio("GE", ".BAS")
			self.gerar_arquivo_vazio("UG", ".BAS")
			self.gerar_arquivo_vazio("OD", ".BAS")
			self.gerar_arquivo_vazio("BD", ".BAL")
			self.gerar_arquivo_vazio("BR", ".BAL")
			self.gerar_arquivo_vazio("RX", ".BAL")
			self.gerar_arquivo_vazio("DX", ".BAL")
			self.gerar_arquivo_vazio("BE", ".BAL")
			self.gerar_arquivo_vazio("BA", ".BAL")
			self.gerar_arquivo_vazio("BB", ".BAL")
			self.gerar_arquivo_vazio("BC", ".BAL")

			if executivo?
				self.gerar_arquivo_vazio("PC", ".RPP")
				self.gerar_arquivo_vazio("AA", ".RPP")
				self.gerar_arquivo_vazio("CN", ".RPP")
				self.gerar_arquivo_vazio("DR", ".RPP")
				self.gerar_arquivo_vazio("ME", ".RPP")
				self.gerar_arquivo_vazio("IN", ".RPP")
				self.gerar_arquivo_vazio("CI", ".RPP")
				self.gerar_arquivo_vazio("AD", ".RPP")
				self.gerar_arquivo_vazio("MI", ".RPP")
				self.gerar_arquivo_vazio("LR", ".RPP")
				self.gerar_arquivo_vazio("AR", ".RPP") if mes_de_geracao == "01"
			end

		# 	puts "Gerando Todos os Arquivos Contabilidade"
		# 	@@erro_lote = nil
		# 	metodos = [
		# 		:gerar_medicoes_das_obras,
		# 		:gerar_notas_fiscais,
		# 		:gerar_itens_das_notas,
		# 		:gerar_pagamentos,
		# 		:gerar_pagamentos_de_folha,
		# 		:gerar_cheque_de_nota_de_pagamento,
		# 		:gerar_deducoes_de_notas_de_pagamento,
		# 		:gerar_estornos_de_liquidacao,
		# 		:gerar_estornos_de_pagamento,
		# 		:gerar_despesas_extra_orcamentarias,
		# 		:gerar_estornos_despesas_extra_orcamentarias,
		# 		:gerar_abertura_de_credito_adicional,
		# 		:gerar_fontes_de_abertura_de_credito_adicional,
		# 		:gerar_remanejamentos_transposicoes_e_transferencias,
		# 		:gerar_destinacao_remanejamentos_transposicoes_e_transferencias,
		# 		:gerar_movimentacao_fontes_de_recurso,
		# 		:gerar_transferencias_federais,
		# 		:gerar_diarias,
		# 		:gerar_obras,
		# 		:gerar_status_da_obra,
		# 		:gerar_transferencias_financeiras,
		# 		:gerar_responsaveis_pela_geracao_e_envio_de_contas_mensais,
		# 		:gera_arquivo_gestores,
		# 		:gerar_contas_bancarias_municipais,
		# 		:gerar_contas_contas_extra_orcamentarias,
		# 		:gerar_arquivo_unidade_gestora,
		# 		:gerar_arquivo_ordenador_de_despesa,
		# 		:gerar_balancetes_de_despesas_orcamentarias,
		# 		:gerar_balancetes_de_receitas_orcamentarias,
		# 		:gerar_balancetes_de_receitas_extras_orcamentarias,
		# 		:gerar_balancetes_de_despesas_extras_orcamentarias,
		# 		:gerar_balancetes_de_receitas_orcamentarias_pcasp,
		# 		:gerar_balancetes_de_despesas_orcamentarias_pcasp,
		# 		:gerar_balancetes_das_contas_bancarias_pcasp,
		# 		:gerar_balancetes_das_contas_pcasp,
		# 	]

		# 	if executivo?
		# 		metodos.concat([
		# 			:gerar_parcelamentos_de_rpps,
		# 			:gerar_acompanhamentos_de_parcelamento_de_rpps,
		# 			:gerar_conselhos_de_rpps,
		# 			:gerar_demonstrativos_de_informacoes_previdenciarias,
		# 			:gerar_membros_do_conselhos_de_rpps,
		# 			:gerar_investimentos_do_rpps,
		# 			:gerar_comites_de_ivestimento_rpps,
		# 			:gerar_aportes_e_despesa,
		# 			:gerar_membros_do_comite_de_ivestimento_rpps,
		# 			:gerar_decretos_de_rpps
		# 		])
		# 		metodos << :gerar_alocacao_de_recursos if mes_de_geracao == "01"
		# 	end

		# 	metodos.uniq.each do |metodo|
		# 		ActiveRecord::Base.transaction do
		# 			begin
		# 				self.send(metodo) if self.respond_to?(metodo)
		# 			rescue => e
		# 				@@erro_lote = @@erro_lote.present? ? @@erro_lote : Tcm::ErrosDoLote.create(tipo: self.tipo, orcamento_id: self.orcamento_id, mes_de_referencia: mes_de_referencia, tipo_de_poder: self.tipo_de_poder, situacao: 2)
		# 			end
		# 		end
		# 	end

		# 	update_column(:situacao, 1) unless todos?
		end
	end

	def gera_todos_os_arquivos_do_patrimonio
		if self.tipo && (self.patrimonio? || self.todos?) && orcamento.present?
			self.gerar_arquivo_vazio("BP", ".PAT")
			self.gerar_arquivo_vazio("BO", ".PAT")
			self.gerar_arquivo_vazio("BN", ".PAT")
			self.gerar_arquivo_vazio("RB", ".PAT")
			self.gerar_arquivo_vazio("RP", ".PAT")

			# puts "Gerando Todos os Arquivos do Patrimonio"
			# metodos = [
			# 	:gera_bens_patrimoniais,
			# 	:gera_bens_patrimoniais_por_unidade,
			# 	:gera_bens_por_empenho,
			# 	:gera_contas_redutoras_patrimonial
			# ]

			# metodos.uniq.each do |metodo|
			# 	ActiveRecord::Base.transaction do
			# 		begin
			# 			self.send(metodo) if self.respond_to?(metodo)
			# 		rescue => e
			# 			@@erro_lote = @@erro_lote.present? ? @@erro_lote : Tcm::ErrosDoLote.create(tipo: self.tipo, orcamento_id: self.orcamento_id, mes_de_referencia: mes_de_referencia, tipo_de_poder: self.tipo_de_poder, situacao: 2)
			# 		end
			# 	end
			# end
			# update_column(:situacao, 1)
		end
	end

	def gera_todos_os_arquivos_em_segundo_plano
		if self.tipo.present?
			self.gera_todos_os_arquivos_da_licitacao
			self.gera_todos_os_arquivos_do_orcamento
			self.gera_todos_os_arquivos_da_contabilidade
			self.gera_todos_os_arquivos_do_patrimonio
    end
	end

	#CONTABILIDADE METODOS
	def deve_existir_responsaveis_para_gerar_o_lote
		configuracao = Configuracao.last
		if configuracao.deve_existir_todos_os_responsaveis(poder_associado)
			errors[:base ] << "Os Responsáveis para envio do SIM não estão cadastrados."
		end
	end


	def gera_arquivo(arquivo, tipo_de_poder, coluna_referencia, classe_do_arquivo = nil)
		#arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")
		nome_do_arquivo = arquivo.nome
		nome_do_arquivo = nome_do_arquivo.first(8) if nome_do_arquivo.first(2) == "CP" # alteração realizada para na consulta poder encontrar as linhas de cheque de pagamento já que o arquivo referencia é estruturado de uma forma diferente dos demais
	
		Tcm::Linha.find_by_sql("SELECT * FROM tcm_linhas WHERE  arquivo_referencia like '%#{nome_do_arquivo}%' AND tipo_de_poder = #{tipo_de_poder = Tcm::Linha.tipos_de_poder[tipo_de_poder]} AND arquivo_id IS NULL ORDER BY modulo_id ASC").each do |linha|
			arquivo.conteudo << linha.conteudo
			arquivo.conteudo << "\r\n"
			arquivo.classe = (classe_do_arquivo.present? ? classe_do_arquivo : linha.modulo_type)
			linha.update_column(:arquivo_id, arquivo.id)
			linha.modulo.update_column(coluna_referencia.to_sym, arquivo.id)
			linha.modulo.gera_linha_para_arquivo_do_sim if nome_do_arquivo.first(2) == "LQ" # Será chamado para realizar a marcação do arquivo_id para o agrupamento das liquidações na qual essa linha pertence. 		
		end

		salva_ou_deleta_arquivo(arquivo)
end

	def gera_arquivo_gestores(arquivo)
		puts "Gerando Gestores"
		# nome_do_arquivo = "GE" + exercicio_e_mes_de_geracao + ".BAS"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		contexto_atual = contexto_atual.present? ? contexto_atual : Orcamento.find_by(exercicio: data_referencia.year)
		gestores = Tcm::Lote.retorna_gestores(data_referencia, poder_associado, contexto_atual)
		gestores.each do |gestor|
			gestor.unidade_gestora.unidades_orcamentarias.joins(:orgao).where(' loa_orgaos.orcamento_id = ? AND loa_unidades_orcamentarias.data_de_inclusao <= ?', contexto_atual.id, data_referencia.end_of_month).each do |unidade_orcamentaria|
				arquivo.conteudo << gestor.to_sim(exercicio_e_mes_de_geracao, unidade_orcamentaria.id)
				arquivo.conteudo << "\r\n"
				if gestor.inicio_da_gestao.between?(data_referencia, data_referencia.end_of_month)
					arquivo.classe = gestor.class.name
					gestor.update_column(:arquivo_id, arquivo.id)
				else
					arquivo.classe = 'Gestor::Final'
					gestor.update_column(:arquivo_final_id, arquivo.id)
				end
			end
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_arquivo_unidade_gestora(arquivo)
		puts "Gerando Unidades Gestoras"
		# nome_do_arquivo = "UG" + exercicio_e_mes_de_geracao + ".BAS"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		unidades_gestoras = retorna_unidades_gestoras(poder_associado)
		unidades_gestoras.each do |unidade_gestora|
			unidade_gestora.unidades_orcamentarias.joins(orgao: :orcamento).where('orcamentos.exercicio = ? AND loa_unidades_orcamentarias.data_de_inclusao <= ?', data_referencia.year, data_referencia.end_of_month).each do |unidade_orcamentaria|
				arquivo.conteudo << unidade_gestora.to_sim(exercicio_e_mes_de_geracao, data_referencia, unidade_orcamentaria.id)
				arquivo.conteudo << "\r\n"
				arquivo.classe = unidade_gestora.class.name
				unidade_gestora.update_column(:arquivo_id, arquivo.id)
			end
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_arquivo_ordenador_de_despesa(arquivo)
		puts "Gerando Ordenadores de Despesas"
		# nome_do_arquivo = "OD" + exercicio_e_mes_de_geracao + ".BAS"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		contexto_atual = contexto_atual.present? ? contexto_atual : Orcamento.find_by(exercicio: data_referencia.year)
		ordenadores_de_despesa = Tcm::Lote.retorna_ordenadores_de_despesa(data_referencia, poder_associado, contexto_atual)
		ordenadores_de_despesa.each do |ordenador_de_despesa|
			arquivo.conteudo << ordenador_de_despesa.to_sim(exercicio_e_mes_de_geracao, data_referencia)
			arquivo.conteudo << "\r\n"
			if ordenador_de_despesa.data_inicio_da_gestao.between?(data_referencia, data_referencia.end_of_month)
				arquivo.classe = ordenador_de_despesa.class.name
				ordenador_de_despesa.update_column(:arquivo_id, arquivo.id)
			else
				arquivo.classe = 'OrdenadorDeDespesa::Final'
				ordenador_de_despesa.update_column(:arquivo_final_id, arquivo.id)
			end
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_balancetes_de_despesas_orcamentarias(arquivo)
		puts "Gerando Balancete de Despesas Orcamentarias"
		# nome_do_arquivo = "BD" + exercicio_e_mes_de_geracao + ".BAL"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		balancetes = retorna_balancetes_de_despesas_orcamentarias(data_referencia, poder_associado)
		
		balancetes.each do |balancete|
			if balancete.verifica_se_balancete_valido(data_referencia, poder_associado)
				arquivo.conteudo << balancete.to_sim_balancetes_de_despesas_orcamentarias(data_referencia, exercicio_e_mes_de_geracao, poder_associado)
				arquivo.conteudo << "\r\n"
				arquivo.classe = "Loa::BalanceteDeDespesaOrcamentaria"
			end
		end
		
		salva_ou_deleta_arquivo(arquivo)
	end
	

	def gerar_balancetes_de_receitas_orcamentarias(arquivo)
		puts "Gerando Balancete de Receitas Orcamentarias"
		# nome_do_arquivo = "BR" + exercicio_e_mes_de_geracao + ".BAL"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		balancetes = Tcm::Lote.retorna_balancetes_de_recitas_orcamentarias(data_referencia, poder_associado)
		balancetes.each do |balancete|
			if balancete.valor_arrecadado_periodo(data_referencia) != 0 || balancete.valor.to_d != 0
				balancete_de_receitas = balancete.balancetes_de_receita_orcamentaria
				balancete_de_receitas.create
				balancete_de_receitas.last.data_de_envio = Date.today
				balancete_de_receitas.last.exercicio = balancete.unidade_orcamentaria_por_natureza_da_receita.unidade_orcamentaria.orgao.orcamento.exercicio
				balancete_de_receitas.last.arquivo_id = arquivo.id
				balancete_de_receitas.last.save!

				arquivo.conteudo << balancete.to_sim_balancetes_de_receitas_orcamentarias(data_referencia)
				arquivo.conteudo << "\r\n"
				arquivo.classe = balancete_de_receitas.first.class.name
			end
		end
		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_balancetes_de_despesas_extras_orcamentarias(arquivo)
		puts "Gerando Balancete de Despesa Extra Orcamentarias"
		# nome_do_arquivo = "DX" + exercicio_e_mes_de_geracao + ".BAL"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		lista_balancetes = Tcm::Lote.retorna_balancetes_de_despesas_e_receita_extra_orcamentarias(data_referencia, poder_associado)
		lista_balancetes.group_by { |balancete|
			[
				balancete.conta_extra_orcamentaria.codigo_para_o_sim(balancete.unidade_orcamentaria_id),
				balancete.unidade_orcamentaria
			]
		}.each do |criterios, balancetes|
			unidade_orcamentaria = criterios[1]
			args = {
				valor_das_anulacoes_mes: balancetes.inject(0) { |total, bal| total + bal.valor_das_anulacoes_das_despesas_no_mes(data_referencia).to_d },
				valor_das_anulacoes_periodo: balancetes.inject(0) { |total, bal| total + bal.valor_das_anulacoes_das_despesas_no_periodo(data_referencia).to_d },
				valor_pago_das_deducoes_mes: balancetes.inject(0) { |total, bal| total + bal.valor_pago_das_despesas_no_mes(data_referencia).to_d },
				valor_pago_das_deducoes_periodo: balancetes.inject(0) { |total, bal| total + bal.valor_pago_das_despesas_no_periodo(data_referencia).to_d }
			}

			if args[:valor_pago_das_deducoes_periodo].to_d > 0
				balancete_de_depesa_extra = balancetes.first.balancetes_de_despesas_extra_orcamentarias.create(data_de_envio: Date.today, exercicio: balancetes.first.unidade_orcamentaria.orgao.orcamento.exercicio, arquivo_id: arquivo.id)			
				arquivo.conteudo << balancetes.first.to_sim_balancetes_de_despesas_extra_orcamentarias(data_referencia, args)
				arquivo.conteudo << "\r\n"
				arquivo.classe = balancete_de_depesa_extra.class.name
			end
		end

		# A PARTIR DE 2025
		if self.orcamento.exercicio >= 2025
			# pesquisa restos a pagar
			pagamentos = Contabilidade::Pagamento
				.joins(liquidacao: [empenho: [:orcamento, [unidade_orcamentaria: :orgao], [orcamento_da_despesa:[elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]]]])
				.where(data: data_referencia.to_date.beginning_of_year..data_referencia.to_date.end_of_month, resto_a_pagar: true)
				.where('base_tipos_de_unidades_administrativas.poder_associado = ?', self.poder_associado)
				.select("exercicio, contabilidade_pagamentos.data as data, loa_orgaos.codigo AS codigo_orgao, loa_unidades_orcamentarias.codigo AS codigo_unidade, contabilidade_pagamentos.valor, base_tipos_de_unidades_administrativas.poder_associado, 'pagamento' AS tipo")
			estornos = Contabilidade::EstornoDePagamento
				.joins(pagamento: [liquidacao: [empenho: [:orcamento, [unidade_orcamentaria: :orgao], [orcamento_da_despesa:[elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]]]]])
				.where(data_do_estorno: data_referencia.to_date.beginning_of_year..data_referencia.to_date.end_of_month, contabilidade_pagamentos: {resto_a_pagar: true})
				.where('base_tipos_de_unidades_administrativas.poder_associado = ?', self.poder_associado)
				.select("exercicio, data_do_estorno as data, loa_orgaos.codigo AS codigo_orgao, loa_unidades_orcamentarias.codigo AS codigo_unidade, contabilidade_pagamentos.valor, base_tipos_de_unidades_administrativas.poder_associado, 'estorno' AS tipo")
			
			resultado = pagamentos.to_a + estornos.to_a

			resultado.group_by { |item| [item.exercicio, item.codigo_orgao, item.codigo_unidade, item.poder_associado] }.each do |grupo, itens|
				exercicio, codigo_orgao, codigo_unidade, poder_associado = grupo
				texto = ""
				texto << "304".sim_preenche(3) + ","  #1
				texto << Configuracao.first.codigo_do_municipio_no_tcm.sim_preenche(3) + "," #2
				texto << "#{exercicio}00" + "," #3
				texto << codigo_orgao.sim_preenche(2) + ","#4
				texto << codigo_unidade.codigo_uo_to_sim + ","#5
				if poder_associado == 1
					texto << "10000#{exercicio}" + ","#6
				else
					texto << "20000#{exercicio}" + ","#6
				end
				texto << data_referencia.sim_data.sim_limite_sem_aspas(6) + "," #7
				texto << '"G"'+ "," #8  Consultor Lukas falou que sempre iria ser "G"
				texto << itens.select { |i| i.tipo == 'estorno' && i.data >= data_referencia.to_date && i.data <= data_referencia.to_date.end_of_month}.map{|i| i["valor"]}.sum.to_f.to_s.sim_valor + ","
				texto << itens.select { |i| i.tipo == 'estorno' && i.data >= data_referencia.to_date.beginning_of_year && i.data <= data_referencia.to_date.end_of_month}.map{|i| i["valor"]}.sum.to_f.to_s.sim_valor + ","
				texto << itens.select { |i| i.tipo == 'pagamento' && i.data >= data_referencia.to_date && i.data <= data_referencia.to_date.end_of_month}.map(&:valor).sum.to_f.to_s.sim_valor + ","
				texto << itens.select { |i| i.tipo == 'pagamento' && i.data >= data_referencia.to_date.beginning_of_year && i.data <= data_referencia.to_date.end_of_month}.map(&:valor).sum.to_f.to_s.sim_valor
				arquivo.conteudo << "#{texto}\r\n"
			end
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_balancetes_de_receitas_extras_orcamentarias(arquivo)
		puts "Gerando Balancete de Receitas Extra Orcamentarias"
		# nome_do_arquivo = "RX" + exercicio_e_mes_de_geracao + ".BAL"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		lista_balancetes = Tcm::Lote.retorna_balancetes_de_despesas_e_receita_extra_orcamentarias(data_referencia, poder_associado)
				lista_balancetes.group_by { |balancete|
			[
				balancete.conta_extra_orcamentaria.codigo_para_o_sim(balancete.unidade_orcamentaria_id),
				balancete.unidade_orcamentaria
			]
		}.each do |criterios, balancetes|
			unidade_orcamentaria = criterios[1]
			args = {
				valor_cancelado_mes: balancetes.inject(0) { |total, bal| total + bal.conta_extra_orcamentaria.valor_cancelado_no_mes(data_referencia).to_d },
				valor_arrecadado_periodo: balancetes.inject(0) { |total, bal| total + bal.conta_extra_orcamentaria.valor_cancelado_ate_a_data(data_referencia.end_of_month).to_d },
				valor_receita_mes: balancetes.inject(0) { |total, bal| total + bal.conta_extra_orcamentaria.lancamentos_extraorcamentario_receita_por_unidade_no_mes(unidade_orcamentaria.id, data_referencia).sum(&:valor).to_d},
				valor_receitas_periodo: balancetes.inject(0) { |total, bal| total + bal.conta_extra_orcamentaria.lancamentos_extraorcamentario_receita_por_unidade_e_data(unidade_orcamentaria.id, data_referencia.end_of_month).sum(&:valor).to_d}
			}

			if args[:valor_receitas_periodo].to_d > 0
				balancete_de_receita_extra = balancetes.first.balancetes_de_receitas_extra_orcamentarias.create(exercicio: exercicio_e_mes_de_geracao[0..3].to_i, mes_referencia: exercicio_e_mes_de_geracao[4..5].to_i, arquivo_id: arquivo.id)
				arquivo.conteudo << balancetes.first.to_sim(data_referencia, args)
				arquivo.conteudo << "\r\n"
				arquivo.classe = balancete_de_receita_extra.class.name
			end
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_deducoes_de_notas_de_pagamento(arquivo)
		puts "Gerando Deduções de nota de pagamento"
		# nome_do_arquivo = "DP" + exercicio_e_mes_de_geracao + ".DCD"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		deducoes_de_notas_de_pagamento = Tcm::Lote.retorna_deducoes_de_notas_de_pagamento(data_referencia, poder_associado)

		deducoes_de_notas_de_pagamento.group_by { |deducao| 
			[
				deducao.pagamento,
				deducao.conta_extra_orcamentaria.try(:codigo_para_o_sim, deducao.unidade_orcamentaria.id)
			]
		}.each do |criterios, deducoes|
			args = {
				pagamento: criterios[0],
				conta_extra_orcamentaria: criterios[1],
				total: deducoes.sum(&:valor_calculado)
			}

			arquivo.conteudo << deducoes.first.to_sim(exercicio_e_mes_de_geracao, args)
			arquivo.conteudo << "\r\n"
			arquivo.classe = deducoes.first.class.name

			deducoes.each do |deducao|
				deducao.update_column(:arquivo_id, arquivo.id)
			end
		end
		# deducoes_de_notas_de_pagamento.each do |deducao_de_nota|
		# 	arquivo.conteudo << deducao_de_nota.to_sim(exercicio_e_mes_de_geracao)
		# 	arquivo.conteudo << "\r\n"
		# 	arquivo.classe = deducao_de_nota.class.name

		# 	deducao_de_nota.update_column(:arquivo_id, arquivo.id)
		# end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_estornos_de_liquidacao(arquivo)
		puts "Gerando Estornos de Liquidação"
		# nome_do_arquivo = "EL" + exercicio_e_mes_de_geracao + ".DCD"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		estornos_de_liquidacao = Tcm::Lote.retorna_estornos_de_liquidacao(data_referencia, poder_associado)
		estornos_de_liquidacao.each do |estorno_de_liquidacao|
			arquivo.conteudo << estorno_de_liquidacao.to_sim(exercicio_e_mes_de_geracao)
			arquivo.conteudo << "\r\n"
			arquivo.classe = estorno_de_liquidacao.class.name

			estorno_de_liquidacao.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_estornos_de_pagamento(arquivo)
		puts "Gerando Estornos de Pagamentos"
		# nome_do_arquivo = "EG" + exercicio_e_mes_de_geracao + ".DCD"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		estornos_de_pagamento = Tcm::Lote.retorna_estornos_de_pagamento(data_referencia, poder_associado)
		estornos_de_pagamento.each do |estorno_de_pagamento|
			arquivo.conteudo << estorno_de_pagamento.to_sim(exercicio_e_mes_de_geracao, poder_associado)
			arquivo.conteudo << "\r\n"
			arquivo.classe = estorno_de_pagamento.class.name

			estorno_de_pagamento.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_despesas_extra_orcamentarias(arquivo)
		puts "Gerando Despesas Extra Orcamentárias"
		# nome_do_arquivo = "XD" + exercicio_e_mes_de_geracao + ".DCD"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		despesas_extra = Tcm::Lote.retorna_despesas_extra(data_referencia, poder_associado)
		despesas_extra.each do |despesa_extra|
			arquivo.conteudo << despesa_extra.to_sim(exercicio_e_mes_de_geracao)
			arquivo.conteudo << "\r\n"
			arquivo.classe = despesa_extra.class.name

			despesa_extra.update_column(:arquivo_id, arquivo.id)
		end


		if self.orcamento.exercicio >= 2025
			# pesquisa restos a pagar
			pagamentos = Contabilidade::Pagamento
				.joins(liquidacao: [empenho: [:orcamento, [unidade_orcamentaria: :orgao], [orcamento_da_despesa:[elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]]]])
				.where(data: data_referencia.to_date.beginning_of_month..data_referencia.to_date.end_of_month, resto_a_pagar: true)
				.where('base_tipos_de_unidades_administrativas.poder_associado = ?', self.poder_associado)
				.distinct
				.select("exercicio, contabilidade_pagamentos.* , loa_orgaos.codigo AS codigo_orgao, loa_unidades_orcamentarias.codigo AS codigo_unidade, base_tipos_de_unidades_administrativas.poder_associado")

			pagamentos.each do |pagamento|
				begin
					conta = pagamento.contas_bancarias_por_pagamento.first
					numero_de_identificacao = pagamento.cheque? ? pagamento.numero_do_cheque.sim_preenche_a_direita(pagamento.numero_do_cheque.length + 1).delete('"') : pagamento.try(:numero)

					if pagamento.cheque?
						tipo_pagamento = 1
					elsif pagamento.caixa?
						tipo_pagamento = 9
					else
						tipo_pagamento = 2
					end

					texto = ""
					texto << "614".sim_preenche(3) + ","  #1
					texto << Configuracao.first.codigo_do_municipio_no_tcm.sim_preenche(3) + "," #2
					texto << pagamento.exercicio.to_s.sim_limite_sem_aspas(4, "00") + "," #3
					texto << pagamento.codigo_orgao.sim_preenche(2) + ","
					texto << pagamento.codigo_unidade.codigo_uo_to_sim + ","
					texto << (pagamento.poder_associado == 1 ? "10000#{pagamento.exercicio}" : "20000#{pagamento.exercicio}") + "," #6

					if conta.conta_bancaria.conta_caixa?
						texto << "9999".sim_preenche(4) + "," #7
						texto << "999999".sim_preenche(6) + "," #8
						texto << "9999999999".sim_preenche(10) + "," #9
					else
						texto << conta.conta_bancaria.agencia.banco.numero_do_banco.to_s.sim_preenche(4) + "," #7
						texto << conta.conta_bancaria.agencia.numero_da_agencia.to_s.delete(".\/-").first(4).sim_preenche(6)	+ "," #8
						texto << conta.conta_bancaria.numero_da_conta.gsub("-",'').gsub(".",'').sim_preenche(10) + "," #9
					end

					texto << numero_de_identificacao.to_s.sim_limite(10) + "," #10
					texto << data_referencia.sim_data.first(6) + "," #11
					texto << numero_de_identificacao.to_s.sim_limite(10) + "," #12
					texto << pagamento.data.to_date.sim_data + "," #13
					texto << (pagamento.valor_pago.to_f > 0 ? pagamento.valor_pago : pagamento.valor).to_f.to_s.sim_valor + "," #14
					texto << (pagamento.valor_pago.to_f > 0 ? pagamento.valor.to_f - pagamento.valor_pago.to_f : 0).to_s.sim_valor + "," #15
					texto << tipo_pagamento.to_s + "," #16
					texto << pagamento.liquidacao.empenho.pessoa.nome.sim_limite(60) + "," #17
					texto << data_referencia.sim_data.first(6) + "," #18
					texto << (pagamento.valor_pago.to_f > 0 ? pagamento.valor_pago : pagamento.valor).to_f.to_s.sim_valor + "," #19
					texto << "0.00" #20
				rescue => e
				end

				arquivo.conteudo << "#{texto}\r\n"
			rescue => e
			end
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_estornos_despesas_extra_orcamentarias(arquivo)
		puts "Gerando Estornos Despesas Extra Orcamentárias"
		# nome_do_arquivo = "XE" + exercicio_e_mes_de_geracao + ".DCD"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		estornos_de_despesas_extra = Tcm::Lote.retorna_estorno_de_despesas_extra(data_referencia, poder_associado)
		estornos_de_despesas_extra.each do |estorno_de_despesa_extra|
			arquivo.conteudo << estorno_de_despesa_extra.to_sim(exercicio_e_mes_de_geracao, poder_associado)
			arquivo.conteudo << "\r\n"
			arquivo.classe = estorno_de_despesa_extra.class.name
			estorno_de_despesa_extra.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_abertura_de_credito_adicional(arquivo)
		system('rake db:define_numero_para_dotacao')

		puts "Gerando Abertura de Credito Adicional"
		# nome_do_arquivo = "CA" + exercicio_e_mes_de_geracao + ".CRD"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		abertura_de_creditos_adicional = Tcm::Lote.retorna_abertura_de_creditos_adicional(data_referencia, poder_associado)
		abertura_de_creditos_adicional.each do |abertura_de_credito_adicional|
			arquivo.conteudo << abertura_de_credito_adicional.to_sim(exercicio_e_mes_de_geracao)
			arquivo.conteudo << "\r\n"
			arquivo.classe = abertura_de_credito_adicional.class.name
			abertura_de_credito_adicional.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	# def gerar_abertura_de_credito_adicional
	# 	nome_do_arquivo = "CA" + exercicio_e_mes_de_geracao + ".CRD"

	# 	arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

	# 	solicitacao_de_alteracoes_orcamentaria = Contabilidade::SolicitacaoDeAlteracaoOrcamentaria.joins(:decreto).where('contabilidade_decretos.arquivo_id is null AND contabilidade_solicitacao_de_alteracao_orcamentarias.origem_do_recurso in (0, 2, 3, 5) AND contabilidade_decretos.tipo_de_decreto = 0 AND contabilidade_decretos.data_da_legislacao >= ? AND contabilidade_decretos.data_da_legislacao < ? and contabilidade_solicitacao_de_alteracao_orcamentarias.status = 4', data_referencia, data_referencia + 1.months).distinct.all

	# 	dotacao_destino_grouped = []
	# 	solicitacao_de_alteracoes_orcamentaria.each do |solicitacao_de_alteracao_orcamentaria|
	# 		dotacao_destino_grouped << solicitacao_de_alteracao_orcamentaria.dotacoes_destino.group_by { |dotacao_destino| 
	# 			[
	# 				dotacao_destino.orcamento_da_despesa.unidade_orcamentaria.orgao.codigo,
	# 				dotacao_destino.orcamento_da_despesa.unidade_orcamentaria.codigo,
	# 				dotacao_destino.orcamento_da_despesa.subacao.funcao.codigo,
	# 				dotacao_destino.orcamento_da_despesa.subacao.subfuncao.codigo,
	# 				dotacao_destino.orcamento_da_despesa.acao.programa_de_governo.codigo,
	# 				dotacao_destino.orcamento_da_despesa.acao.natureza_da_acao.codigo,
	# 				dotacao_destino.orcamento_da_despesa.acao.codigo,
	# 				dotacao_destino.orcamento_da_despesa.subacao.codigo,
	# 				dotacao_destino.orcamento_da_despesa.elemento_de_despesa.codigo,
	# 				dotacao_destino.orcamento_da_despesa.fonte_de_recursos.codigo_completo,
	# 				dotacao_destino.solicitacao_de_alteracao_orcamentaria.tipo_de_credito_to_sim,
	# 				dotacao_destino.solicitacao_de_alteracao_orcamentaria.origem_do_recurso_to_sim
	# 			]
	# 		}
	# 	end

	# 	resultado = {}

	# 	dotacao_destino_grouped.each do |hash|
	# 		hash.each do |chaves, valores|
	# 			resultado[chaves] ||= []
	# 			resultado[chaves] += valores
	# 		end
	# 	end
	
	# 	resultado.each do |criterios, movimentos|

	# 		total_superavit_financeiro = 0
	# 		total_execesso_de_arrecadacao = 0
	# 		total_operacao_de_credito = 0
	# 		total_anulacao_de_dotacao = 0
	# 		movimentos.each do |movimento|
	# 			total_superavit_financeiro += movimento.valor if movimento.solicitacao_de_alteracao_orcamentaria.superavit_financeiro?
	# 			total_execesso_de_arrecadacao += movimento.valor if movimento.solicitacao_de_alteracao_orcamentaria.execesso_de_arrecadacao?
	# 			total_operacao_de_credito += movimento.valor if movimento.solicitacao_de_alteracao_orcamentaria.operacao_de_credito?
	# 			total_anulacao_de_dotacao += movimento.valor if movimento.solicitacao_de_alteracao_orcamentaria.anulacao_de_dotacao?

	# 		end

	# 		args = {
	# 			orgao: criterios[0],
	# 			unidade_orcamentaria: criterios[1],
	# 			funcao: criterios[2],
	# 			subfuncao: criterios[3],
	# 			programa_de_governo: criterios[4],
	# 			natureza_da_acao: criterios[5],
	# 			acao: criterios[6],
	# 			subacao: criterios[7],
	# 			elemento_de_despesa: criterios[8],
	# 			fonte_de_recursos: criterios[9],
	# 			tipo_de_credito_to_sim: criterios[10],
	# 			origem_do_recurso_to_sim: criterios[11],
	# 			total_superavit_financeiro: total_superavit_financeiro,
	# 			total_execesso_de_arrecadacao: total_execesso_de_arrecadacao,
	# 			total_operacao_de_credito: total_operacao_de_credito,
	# 			total_anulacao_de_dotacao: total_anulacao_de_dotacao,
	# 			sequencia: movimentos.first.id
	# 		}

	# 		arquivo.conteudo << movimentos.first.solicitacao_de_alteracao_orcamentaria.to_sim_credito_adicional(exercicio_e_mes_de_geracao, args)
	# 		arquivo.conteudo << "\r\n"
	# 		arquivo.classe = movimentos.first.solicitacao_de_alteracao_orcamentaria.class.name
	# 	end

	# 	solicitacao_de_alteracoes_orcamentaria.each do |solicitacao_de_alteracao_orcamentaria|
	# 		solicitacao_de_alteracao_orcamentaria.update_column(:arquivo_id, arquivo.id)
	# 	end

	# 	salva_ou_deleta_arquivo(arquivo)
	# end

	def gerar_fontes_de_abertura_de_credito_adicional(arquivo)
		puts "Gerando Fontes de Abertura de Credito Adicional"
		# nome_do_arquivo = "FA" + exercicio_e_mes_de_geracao + ".CRD"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		abertura_de_creditos_adicional = Tcm::Lote.retorna_fonte_abertura_de_creditos_por_anulacao_de_dotacao(data_referencia, poder_associado)
		abertura_de_creditos_adicional.each do |abertura_de_credito_adicional|
			arquivo.conteudo << abertura_de_credito_adicional.to_sim_fonte_anulacao(exercicio_e_mes_de_geracao)
			arquivo.conteudo << "\r\n"
			arquivo.classe = abertura_de_credito_adicional.class.name
			abertura_de_credito_adicional.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_remanejamentos_transposicoes_e_transferencias(arquivo)
		system('rake db:define_numero_para_dotacao[true]')

		puts "Gerando Remaejamentos Transposições e Transferencias"
		# nome_do_arquivo = "RT" + exercicio_e_mes_de_geracao + ".CRD"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		abertura_de_creditos_adicional = Tcm::Lote.retorna_remanejamentos_transposicoes_e_transferencias(data_referencia, poder_associado)
		abertura_de_creditos_adicional.each do |abertura_de_credito_adicional|
			arquivo.conteudo << abertura_de_credito_adicional.to_sim_remanejamentos_transposicoes_e_transferencias(exercicio_e_mes_de_geracao)
			valor = abertura_de_credito_adicional.valor #Contabilidade::DotacaoOrigem.joins(solicitacao_de_alteracao_orcamentaria: :decreto).where("contabilidade_dotacoes_origem.dotacao_id = ? AND contabilidade_dotacoes_origem.arquivo_id_rtt is null", abertura_de_credito_adicional.dotacao_id).where('contabilidade_solicitacao_de_alteracao_orcamentarias.status = ?', 4).where('contabilidade_decretos.data_da_legislacao >=? AND contabilidade_decretos.data_da_legislacao < ? AND contabilidade_decretos.classificacao in (?)', data_referencia, data_referencia + 1.months, ["0", "1", "2"]).all.sum(:valor)
			arquivo.conteudo << valor.round(2).to_f.to_s  #20
			arquivo.conteudo << "\r\n"
			arquivo.classe = abertura_de_credito_adicional.class.name
			abertura_de_credito_adicional.update_column(:arquivo_id_rtt, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_destinacao_remanejamentos_transposicoes_e_transferencias(arquivo)
		puts "Gerando Destinação Remaejamentos Transposições e Transferencias"
		# nome_do_arquivo = "DT" + exercicio_e_mes_de_geracao + ".CRD"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		abertura_de_creditos_adicional = Tcm::Lote.retorna_destinacao_remanejamentos_transposicoes_e_transferencias(data_referencia, poder_associado)
		abertura_de_creditos_adicional.each do |abertura_de_credito_adicional|
			arquivo.conteudo << abertura_de_credito_adicional.to_sim_remanejamentos_transposicoes_e_transferencias(exercicio_e_mes_de_geracao)
			valor = abertura_de_credito_adicional.valor #Contabilidade::DotacaoDestino.joins(solicitacao_de_alteracao_orcamentaria: :decreto).where("contabilidade_dotacoes_destino.dotacao_id = ? AND contabilidade_dotacoes_destino.arquivo_id_rtt is null", abertura_de_credito_adicional.dotacao_id).where('contabilidade_solicitacao_de_alteracao_orcamentarias.status = ?', 4).where('contabilidade_decretos.data_da_legislacao >=? AND contabilidade_decretos.data_da_legislacao < ? AND contabilidade_decretos.classificacao in (?)', data_referencia, data_referencia + 1.months, ["0", "1", "2"]).all.sum(:valor)
			arquivo.conteudo << valor.round(2).to_f.to_s #18
			arquivo.conteudo << "\r\n"
			arquivo.classe = abertura_de_credito_adicional.class.name
			abertura_de_credito_adicional.update_column(:arquivo_id_rtt, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_movimentacao_fontes_de_recurso(arquivo)
		puts "Gerando Movimentação Fontes de Recurso"
		# nome_do_arquivo = "MF" + exercicio_e_mes_de_geracao + ".CRD"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		abertura_de_creditos_adicional = Tcm::Lote.retorna_movimentacao_fontes_de_recurso(data_referencia, poder_associado)
		abertura_de_creditos_adicional.each do |abertura_de_credito_adicional|

			abertura_de_credito_adicional.dotacoes_origem.each do |dotacao_origem|
				codigo_acao_abertura = dotacao_origem.orcamento_da_despesa.subacao.acao.codigo_completo
				codigo_elemento_de_despesa_abertura = dotacao_origem.orcamento_da_despesa.elemento_de_despesa_por_subacao.elemento_de_despesa.codigo_formatado
				codigo_fonte_de_recurso_abertura = dotacao_origem.orcamento_da_despesa.fonte_de_recursos.codigo_completo

				abertura_de_credito_adicional.dotacoes_destino.each do |dotacao_destino|
					codigo_acao_destino = dotacao_destino.orcamento_da_despesa.subacao.acao.codigo_completo
					codigo_elemento_de_despesa_destino = dotacao_destino.orcamento_da_despesa.elemento_de_despesa_por_subacao.elemento_de_despesa.codigo_formatado
					codigo_fonte_de_recurso_destino = dotacao_destino.orcamento_da_despesa.fonte_de_recursos.codigo_completo

					if codigo_acao_abertura == codigo_acao_destino && codigo_elemento_de_despesa_abertura == codigo_elemento_de_despesa_destino && codigo_fonte_de_recurso_abertura != codigo_fonte_de_recurso_destino
						arquivo.conteudo << abertura_de_credito_adicional.to_sim(exercicio_e_mes_de_geracao, dotacao_origem, dotacao_destino)
						arquivo.conteudo << "\r\n"
						arquivo.classe = abertura_de_credito_adicional.class.name
						abertura_de_credito_adicional.update_column(:arquivo_id, arquivo.id)
					end
				end
			end
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_transferencias_federais(arquivo)
		puts "Gerando Transferencias Federais"
		# nome_do_arquivo = "TF" + exercicio_e_mes_de_geracao + ".OUT"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		transferencias_federais = Tcm::Lote.retorna_transferencias_federais(data_referencia, poder_associado)
		transferencias_federais.each do |transferencia_federal|
			arquivo.conteudo << transferencia_federal.to_sim(exercicio_e_mes_de_geracao)
			arquivo.conteudo << "\r\n"
			arquivo.classe = transferencia_federal.class.name
			transferencia_federal.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_diarias(arquivo)
		puts "Gerando Diarias"
		# nome_do_arquivo = "DA" + exercicio_e_mes_de_geracao + ".OUT"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		diarias = Tcm::Lote.retorna_diarias(data_referencia, poder_associado)
		diarias.each do |diaria|
			arquivo.conteudo << diaria.to_sim(exercicio_e_mes_de_geracao)
			arquivo.conteudo << "\r\n"
			arquivo.classe = diaria.class.name
			diaria.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_obras(arquivo)
		puts "Gerando Obras"
		# nome_do_arquivo = "OS" + exercicio_e_mes_de_geracao + ".OSE"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		obras = Tcm::Lote.retorna_obras(data_referencia, poder_associado)
		obras.each do |obra|
			arquivo.conteudo << obra.to_sim
			arquivo.conteudo << "\r\n"
			arquivo.classe = obra.class.name
			obra.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_medicoes_das_obras(arquivo)
		puts "Gerando Medições das Obras"
		# nome_do_arquivo = "MO" + exercicio_e_mes_de_geracao + ".OSE"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		medicoes_das_obras = Tcm::Lote.retorna_medicoes_das_obras(data_referencia, poder_associado)
		medicoes_das_obras.each do |medicao_da_obra|
			arquivo.conteudo << medicao_da_obra.to_sim(exercicio_e_mes_de_geracao)
			arquivo.conteudo << "\r\n"
			arquivo.classe = medicao_da_obra.class.name
			medicao_da_obra.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_status_da_obra(arquivo)
		puts "Gerando Status da Obras"
		# nome_do_arquivo = "SO" + exercicio_e_mes_de_geracao + ".OSE"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		status_das_obras = Tcm::Lote.retorna_status_das_obras(data_referencia, poder_associado)
		status_das_obras.each do |status_da_obra|
			arquivo.conteudo << status_da_obra.to_sim
			arquivo.conteudo << "\r\n"
			arquivo.classe = status_da_obra.class.name
			status_da_obra.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_contas_bancarias_municipais(arquivo)
		"Gerando Contas Bancárias Municipais"
		# nome_do_arquivo = "CB" + exercicio_e_mes_de_geracao + ".BAS"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")
		condicoes_de_data = self.mes_de_referencia == "janeiro" ? "<= '#{data_referencia.end_of_month.sim_data}'" : "BETWEEN '#{data_referencia.sim_data}' AND '#{data_referencia.end_of_month.sim_data}'"

		contas_por_uo = Base::ContaBancariaPorUnidadeOrcamentaria.find_by_sql("
			WITH primeira_mov_da_conta_por_uo AS (
				SELECT conta_bancaria_por_unidade_orcamentaria_id, MIN(data_da_movimentacao) AS min_data_da_movimentacao
				FROM contabilidade_movimentacoes_da_conta_bancaria mov
				INNER JOIN base_contas_bancarias_por_unidade_orcamentaria conta_por_uo ON conta_por_uo.id = mov.conta_bancaria_por_unidade_orcamentaria_id
				INNER JOIN loa_unidades_orcamentarias uo ON uo.id = conta_por_uo.unidade_orcamentaria_id
        INNER JOIN base_tipos_de_unidades_administrativas tipo_admin ON tipo_admin.id = uo.tipo_de_unidade_administrativa_id
        LEFT JOIN orcamentos orc ON tipo_admin.modulo_id = orc.id
        INNER JOIN base_contas_bancarias conta ON conta.id = conta_por_uo.conta_bancaria_id
        WHERE orc.id = #{self.orcamento_id}
        AND conta_por_uo.arquivo_id IS NULL
        AND conta.conta_caixa_pcasp IS FALSE
        AND poder_associado = #{poder_associado}
				GROUP BY conta_bancaria_por_unidade_orcamentaria_id
			)

			SELECT DISTINCT conta_por_uo.*
			FROM base_contas_bancarias_por_unidade_orcamentaria conta_por_uo
			INNER JOIN primeira_mov_da_conta_por_uo min_mov ON min_mov.conta_bancaria_por_unidade_orcamentaria_id = conta_por_uo.id
			WHERE min_mov.min_data_da_movimentacao #{condicoes_de_data};
		")

		contas_por_uo.group_by{|conta| conta.conta_bancaria}.each do |conta_bancaria, contas_por_uo_da_conta|
			contas_por_uo_da_conta.each do |conta_por_uo|
				arquivo.conteudo << conta_bancaria.to_sim(data_referencia, exercicio_e_mes_de_geracao, orcamento, conta_por_uo.unidade_orcamentaria_id)
				arquivo.conteudo << "\r\n"
				arquivo.classe = conta_por_uo.class.name
				conta_por_uo.update_column(:arquivo_id, arquivo.id)
			end
		end
		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_contas_contas_extra_orcamentarias(arquivo)
		"Gerando Contas Extra Orçamentárias"
		contas = retorna_contas_extras(data_referencia, poder_associado)
		contas.group_by{|conta| conta.conta_extra_orcamentaria.codigo_para_o_sim(contas.first.unidade_orcamentaria_id)}.each do |codigo_conta_extra, contas_uo|
			saldo_inicial = contas_uo.map{|conta| conta.saldo.to_f}.sum
			conta_extra = contas_uo[0].conta_extra_orcamentaria
			arquivo.conteudo << conta_extra.to_sim(exercicio_e_mes_de_geracao, saldo_inicial, contas_uo[0].unidade_orcamentaria_id)
			arquivo.conteudo << "\r\n"
			arquivo.classe = contas_uo[0].class.name
			contas_uo.each{|conta| conta.update_column(:arquivo_id, arquivo.id)}
		end

		# a partir de 2025
		if self.orcamento.exercicio >= 2025
			# adiciona items para restos a pagar
			if arquivo.present? && arquivo.lote.mes_de_referencia == "janeiro"
				empenhos = Contabilidade::Empenho.joins(:orcamento).where(restos_a_pagar: true).joins(orcamento_da_despesa:[elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]).where('base_tipos_de_unidades_administrativas.poder_associado = ?', self.poder_associado)
				empenhos.group_by{|empenho| empenho.orcamento.exercicio}.each do |exercicio, empenhos_do_exercicio|

					saldo_inicial = empenhos_do_exercicio.map{|empenho| empenho.valor_processado(self.orcamento).to_f + empenho.valor_nao_processado(self.orcamento).to_f}.sum
					configuracao_codigo = Configuracao.first.codigo_do_municipio_no_tcm.to_s.sim_preenche(3)

					if self.executivo?
						arquivo.conteudo << "\"107\",#{configuracao_codigo},#{exercicio}00,10000#{exercicio},#{exercicio_e_mes_de_geracao},\"Restos a Pagar #{exercicio}\",-#{saldo_inicial.to_s.sim_valor}"
					else
						arquivo.conteudo << "\"107\",#{configuracao_codigo},#{exercicio}00,20000#{exercicio},#{exercicio_e_mes_de_geracao},\"Restos a Pagar #{exercicio}\",-#{saldo_inicial.to_s.sim_valor}"
					end
					arquivo.conteudo << "\r\n"
				end
			end
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_conselhos_de_rpps(arquivo)
		puts "Gerando Conselhos de RPPS"
		# nome_do_arquivo = "CN" + exercicio_e_mes_de_geracao + ".RPP"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		conselhos_de_rpps = retorna_conselhos_de_rpps(data_referencia)
		conselhos_de_rpps.each do |conselho_de_rpps|
			arquivo.conteudo << conselho_de_rpps.to_sim
			arquivo.conteudo << exercicio_e_mes_de_geracao << "\r\n"
			arquivo.classe = conselho_de_rpps.class.name
			conselho_de_rpps.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_decretos_de_rpps(arquivo)
		puts "Gerando Membros Decretos de RPPS"
		# nome_do_arquivo = "LR" + exercicio_e_mes_de_geracao + ".RPP"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		legislacoes_do_rpps = Tcm::Lote.retorna_legislacao_do_rpps(data_referencia)
		legislacoes_do_rpps.each do |legislacao_do_rpps|
			arquivo.conteudo << legislacao_do_rpps.to_sim
			arquivo.conteudo << "\r\n"
			arquivo.classe = legislacao_do_rpps.class.name
			legislacao_do_rpps.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_investimentos_do_rpps(arquivo)
		puts "Gerando Investimentos do RPPS"
		# nome_do_arquivo = "IN" + exercicio_e_mes_de_geracao + ".RPP"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		investimentos_do_rpps = self.retorna_investimentos_do_rpps
		investimentos_do_rpps.each do |investimento_do_rpps|
			arquivo.conteudo << investimento_do_rpps.to_sim(exercicio_e_mes_de_geracao)
			arquivo.conteudo << "\r\n"
			arquivo.classe = investimento_do_rpps.class.name
			investimento_do_rpps.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_demonstrativos_de_informacoes_previdenciarias(arquivo)
		puts "Gerando Demosntrativos de Informações Previdenciarias"
		# nome_do_arquivo = "DR" + exercicio_e_mes_de_geracao + ".RPP"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		demonstrativos_de_informacoes = self.retorna_demonstrativos_de_informacoes_previdenciarias
		demonstrativos_de_informacoes.each do |demonstrativo_de_informacao|
			arquivo.conteudo << demonstrativo_de_informacao.to_sim(exercicio_e_mes_de_geracao)
			arquivo.conteudo << "\r\n"
			arquivo.classe = demonstrativo_de_informacao.class.name
			demonstrativo_de_informacao.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_aportes_e_despesa(arquivo)
		puts "Gerando Aportes e Despesa"
		#nome_do_arquivo = "AD" + exercicio_e_mes_de_geracao + ".RPP"
		#arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		aportes_e_despesa = Tcm::Lote.retorna_aportes_e_despesa(data_referencia)
		aportes_e_despesa.each do |aporte_e_despesa|
			arquivo.conteudo << aporte_e_despesa.to_sim(exercicio_e_mes_de_geracao)
			arquivo.conteudo << "\r\n"
			arquivo.classe = aporte_e_despesa.class.name
			aporte_e_despesa.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_comites_de_ivestimento_rpps(arquivo)
		puts "Gerando Comites de Ibnvestimento RPPS"
		# nome_do_arquivo = "CI" + exercicio_e_mes_de_geracao + ".RPP"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		comites_de_ivestimento = self.retorna_comites_de_ivestimento_rpps(data_referencia)
		comites_de_ivestimento.each do |comite_de_ivestimento|
			arquivo.conteudo << comite_de_ivestimento.to_sim(exercicio_e_mes_de_geracao)
			arquivo.conteudo << exercicio_e_mes_de_geracao << "\r\n"
			arquivo.classe = comite_de_ivestimento.class.name
			comite_de_ivestimento.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_membros_do_comite_de_ivestimento_rpps(arquivo)
		puts "Gerando Membros do Comite de Investimento"
		# nome_do_arquivo = "MI" + exercicio_e_mes_de_geracao + ".RPP"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		membros_do_comite_de_ivestimento = Tcm::Lote.retorna_membros_do_comite_de_ivestimento_rpps(data_referencia)
		membros_do_comite_de_ivestimento.each do |membro_do_comite_de_ivestimento|
			arquivo.conteudo << membro_do_comite_de_ivestimento.to_sim(exercicio_e_mes_de_geracao)
			arquivo.conteudo << exercicio_e_mes_de_geracao << "\r\n"
			arquivo.classe = membro_do_comite_de_ivestimento.class.name
			membro_do_comite_de_ivestimento.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_responsaveis_pela_geracao_e_envio_de_contas_mensais(arquivo)
		puts "Gerando Responsaveis pela Geração e Envio de Contas Mensais"
		# nome_do_arquivo = "RC" + exercicio_e_mes_de_geracao + ".CTR"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		gerar_uma_vez = 0
		responsaveis = Tcm::Lote.retorna_responsaveis_pela_geracao(self.tipo_de_poder)
		responsaveis.each do |responsavel|
			if gerar_uma_vez <= 0
				arquivo.conteudo << responsavel.to_sim
				arquivo.classe = responsavel.class.name
				gerar_uma_vez += 1
			end
			responsavel.update_column(:arquivo_id, arquivo.id)
		end
		gerar_uma_vez = 0

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_alocacao_de_recursos(arquivo)
		# nome_do_arquivo = "AR" + exercicio_e_mes_de_geracao + ".RPP"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		alocacoes_de_recurso = retorna_alocacoes_de_recurso
		alocacoes_de_recurso.each do |alocacao_de_recurso|
			alocacao_de_recurso.percentuais_da_alocacao_de_recurso.where('valor > 0').each do |percentual_da_alocacao_de_recurso|
				arquivo.conteudo << alocacao_de_recurso.to_sim(exercicio_e_mes_de_geracao, percentual_da_alocacao_de_recurso)
				arquivo.conteudo << "\r\n"
			end
			arquivo.classe = alocacao_de_recurso.class.name
			alocacao_de_recurso.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_membros_do_conselhos_de_rpps(arquivo)
		puts "Gerando Membros de Conselhos de RPPS"
		# nome_do_arquivo = "ME" + exercicio_e_mes_de_geracao + ".RPP"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")
		membros_do_conselhos_de_rpps = Tcm::Lote.retorna_membros_do_conselhos_de_rpps(data_referencia)
		membros_do_conselhos_de_rpps.each do |membro_do_conselho_de_rpps|
			arquivo.conteudo << membro_do_conselho_de_rpps.to_sim
			arquivo.conteudo << exercicio_e_mes_de_geracao << "\r\n"

			if membro_do_conselho_de_rpps.data_de_admissao.between?(data_referencia, data_referencia.end_of_month)
				membro_do_conselho_de_rpps.update_column(:arquivo_id, arquivo.id)
			else
				membro_do_conselho_de_rpps.update_column(:arquivo_final_id, arquivo.id)
			end
		end
		arquivo.classe = 'Contabilidade::MembroDoConselhoDoRpps;MembroDoConselhoDoRpps::Final'
		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_parcelamentos_de_rpps(arquivo)
		puts "Gerando Parcelamentos de RPPS"
		# nome_do_arquivo = "PC" + exercicio_e_mes_de_geracao + ".RPP"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		parcelamentos_de_rpps = retorna_parcelamentos_do_rpps(data_referencia)
		parcelamentos_de_rpps.each do |parcelamento_de_rpps|
			arquivo.conteudo << parcelamento_de_rpps.to_sim(exercicio_e_mes_de_geracao)
			arquivo.conteudo << "\r\n"
			arquivo.classe = parcelamento_de_rpps.class.name
			parcelamento_de_rpps.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_acompanhamentos_de_parcelamento_de_rpps(arquivo)
		puts "Gerando Acompanhamentos Parcelamentos de RPPS"
		# nome_do_arquivo = "AP" + exercicio_e_mes_de_geracao + ".RPP"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		acompanhamentos_de_parcelamento_de_rpps = retorna_acompanhamentos_de_parcelamentos_do_rpps(data_referencia)
		acompanhamentos_de_parcelamento_de_rpps.each do |acompanhamento_de_parcelamento_de_rpps|
			arquivo.conteudo << acompanhamento_de_parcelamento_de_rpps.to_sim(exercicio_e_mes_de_geracao)
			arquivo.conteudo << "\r\n"
			arquivo.classe = acompanhamento_de_parcelamento_de_rpps.class.name
			acompanhamento_de_parcelamento_de_rpps.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	# ORÇAMENTO
	def existem_dados_do_orcamento_a_serem_enviados
		if orcamento && self.orcamento?
			orgaos_ids = orcamento.orgaos.where("arquivo_id is null").ids
			programas_de_governo_ids = orcamento.programas_de_governo.where("arquivo_id is null").ids

			unidades_orcamentarias_ids = Loa::UnidadeOrcamentaria.where("arquivo_id is null and orgao_id in (?)", orgaos_ids).ids
			subacoes_ids = Loa::Subacao.where("unidade_orcamentaria_id in (?)", unidades_orcamentarias_ids).ids
			elementos_de_despesas_por_subacoes_ids = Loa::ElementoDeDespesaPorSubacao.where("subacao_id in (?)", subacoes_ids).ids
			unidades_orcamentarias_por_natureza_da_receita_ids = Loa::UnidadeOrcamentariaPorNaturezaDaReceita.where("unidade_orcamentaria_id in (?)", unidades_orcamentarias_ids).ids
			
			unless self.mes_de_referencia == 'dezembro'
				orcamentos_da_despesa_ids = Loa::OrcamentoDaDespesa.joins(dotacoes_destino:[solicitacao_de_alteracao_orcamentaria: :decreto]).where("contabilidade_decretos.data_da_legislacao BETWEEN ? AND ?", data_referencia, data_referencia.end_of_month).ids
			else
				orcamentos_da_despesa_ids = Loa::OrcamentoDaDespesa.joins(elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: [orgao: :orcamento]]]).where('Orcamentos.id = ?', contexto_atual.id).ids
			end

			orcamentos_das_receitas_ids = Loa::OrcamentoDaReceita.where("arquivo_id is null and unidade_orcamentaria_por_natureza_da_receita_id in (?)", unidades_orcamentarias_por_natureza_da_receita_ids).ids

			alteracoes_orcamentarias_destino = Contabilidade::DotacaoDestino.joins(solicitacao_de_alteracao_orcamentaria: :decreto).where("contabilidade_decretos.data_da_legislacao >= ? AND contabilidade_decretos.data_da_legislacao < ? and contabilidade_solicitacao_de_alteracao_orcamentarias.status = 4 and contabilidade_solicitacao_de_alteracao_orcamentarias.tipo_de_credito in (1,2) and origem_do_recurso in (0, 2, 3, 5)", data_referencia, data_referencia + 1.months).ids

			unless orcamento.arquivo_id.nil? || orgaos_ids.size > 0 || unidades_orcamentarias_ids.size > 0 || orcamentos_da_despesa_ids.size > 0 || orcamentos_das_receitas_ids.size > 0 || programas_de_governo_ids.size > 0 || alteracoes_orcamentarias_destino.size > 0
				errors[:tipo ] << "no momento não existem dados a enviar para o tipo selecionado."
			end
		end
	end

	def gera_arquivo_de_orcamento(arquivo)
		#nome_do_arquivo = "DO" + exercicio_e_mes_de_geracao + ".ORC"
		#arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		unless orcamento.arquivo_id.present?
			arquivo.conteudo << orcamento.to_sim
			arquivo.conteudo << exercicio_e_mes_de_geracao << "\r\n"
			arquivo.classe = 'Orcamento'
			orcamento.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gera_arquivo_de_orgaos(arquivo)
		# nome_do_arquivo = "OR" + exercicio_e_mes_de_geracao + ".BAS"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		orgaos = orcamento.orgaos.where("arquivo_id is null").all
		orgaos.each do |orgao|
			arquivo.conteudo << orgao.to_sim
			arquivo.conteudo << "\r\n"
			arquivo.classe = 'Loa::Orgao'
			orgao.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gera_arquivo_de_orcamentos_das_receitas(arquivo)
		# nome_do_arquivo = "RE" + exercicio_e_mes_de_geracao + ".ORC"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")
		
		unless self.aprovacao_loa?
			orcamentos_das_receitas = Loa::OrcamentoDaReceita.find_by_sql("SELECT orcr.* FROM loa_orgaos org INNER JOIN loa_unidades_orcamentarias unid ON unid.orgao_id = org.id INNER JOIN loa_unidades_orcamentarias_por_natureza_da_receita unid_nat ON unid_nat.unidade_orcamentaria_id = unid.id INNER JOIN loa_orcamentos_da_receita orcr ON orcr.unidade_orcamentaria_por_natureza_da_receita_id = unid_nat.id WHERE org.orcamento_id = #{orcamento.id} AND ( SELECT MIN(data_do_lancamento) FROM contabilidade_lancamentos_do_orcamento_da_receita lanc WHERE lanc.orcamento_da_receita_id = orcr.id ) BETWEEN '#{data_referencia.sim_data}' AND '#{data_referencia.end_of_month.sim_data}'")
		else
			orcamentos_das_receitas = Loa::OrcamentoDaReceita.find_by_sql("SELECT orcr.* FROM loa_orgaos org INNER JOIN loa_unidades_orcamentarias unid ON unid.orgao_id = org.id INNER JOIN loa_unidades_orcamentarias_por_natureza_da_receita unid_nat ON unid_nat.unidade_orcamentaria_id = unid.id INNER JOIN loa_orcamentos_da_receita orcr ON orcr.unidade_orcamentaria_por_natureza_da_receita_id = unid_nat.id LEFT JOIN contabilidade_lancamentos_do_orcamento_da_receita lanc ON lanc.orcamento_da_receita_id = orcr.id WHERE org.orcamento_id = #{orcamento.id} AND lanc.id IS NULL AND orcr.id NOT IN ( SELECT DISTINCT lanc.orcamento_da_receita_id FROM contabilidade_lancamentos_do_orcamento_da_receita lanc WHERE lanc.data_do_lancamento BETWEEN '#{data_referencia.sim_data}' AND '#{data_referencia.end_of_month.sim_data}')")
		end


		orcamentos_das_receitas.each do |receita|
			arquivo.conteudo << receita.to_sim
			arquivo.conteudo << "\r\n"
			arquivo.classe = 'Loa::OrcamentoDaReceita'
			receita.update_column(:arquivo_id, arquivo.id)

		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gera_arquivo_de_programas_de_governo(arquivo)
		#nome_do_arquivo = "PG" + exercicio_e_mes_de_geracao + ".ORC"
		#arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		programas_de_governo = orcamento.programas_de_governo.where("arquivo_id is null").all
		programas_de_governo.each do |programa_de_governo|
			arquivo.conteudo << programa_de_governo.to_sim
			arquivo.conteudo << "\r\n"
			arquivo.classe = 'Loa::ProgramaDeGoverno'
			programa_de_governo.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gera_arquivo_de_orcamentos_da_despesa_e_elementos_da_despesa(arquivo)
		# nome_do_arquivo = "DE" + exercicio_e_mes_de_geracao + ".ORC"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")
		
		unless self.aprovacao_loa?
			orcamentos_da_despesa = Loa::OrcamentoDaDespesa.find_by_sql("SELECT DISTINCT orcd.* FROM loa_orgaos org INNER JOIN loa_unidades_orcamentarias unid ON unid.orgao_id = org.id INNER JOIN loa_subacoes sub ON sub.unidade_orcamentaria_id = unid.id INNER JOIN loa_elementos_de_despesa_por_subacao elesub ON elesub.subacao_id = sub.id INNER JOIN loa_orcamentos_da_despesa orcd ON orcd.elemento_de_despesa_por_subacao_id = elesub.id INNER JOIN contabilidade_dotacoes_destino dotd ON orcd.id = dotd.dotacao_id INNER JOIN contabilidade_solicitacao_de_alteracao_orcamentarias sol on sol.id = dotd.solicitacao_de_alteracao_orcamentaria_id INNER JOIN contabilidade_decretos dc on dc.id = sol.decreto_id WHERE org.orcamento_id = #{orcamento.id} AND sol.status = 4 AND sol.tipo_de_credito IN (1,2) AND dc.data_da_legislacao BETWEEN '#{data_referencia.sim_data}' AND '#{data_referencia.end_of_month.sim_data}'")
			orcamentos_da_despesa.each do |despesa|
				arquivo.conteudo << despesa.to_sim_orcamento_da_despesa
				arquivo.conteudo << "\r\n"
				arquivo.classe = 'Loa::OrcamentoDaDespesa'
				despesa.update_column(:arquivo_id, arquivo.id)
			end
		else
			orcamentos_da_despesa = Loa::OrcamentoDaDespesa.find_by_sql("SELECT orcd.* FROM loa_orgaos org INNER JOIN loa_unidades_orcamentarias unid ON unid.orgao_id = org.id INNER JOIN loa_subacoes sub ON sub.unidade_orcamentaria_id = unid.id INNER JOIN loa_elementos_de_despesa_por_subacao elesub ON elesub.subacao_id = sub.id INNER JOIN loa_orcamentos_da_despesa orcd ON orcd.elemento_de_despesa_por_subacao_id = elesub.id LEFT JOIN contabilidade_dotacoes_destino dotd ON orcd.id = dotd.dotacao_id WHERE dotd.dotacao_id IS NULL AND org.orcamento_id = #{orcamento.id} AND orcd.valor > 0")
			orcamentos_da_despesa.group_by{|orcd| [orcd.elemento_de_despesa_por_subacao.subacao.unidade_orcamentaria, orcd.elemento_de_despesa_por_subacao.elemento_de_despesa]}.each do |criterios, despesas|
				despesa = despesas.first
				val_agrupado = despesas.sum(&:valor)
				arquivo.conteudo << despesa.to_sim_orcamento_da_despesa(val_agrupado)
				arquivo.conteudo << "\r\n"
				arquivo.classe = 'Loa::OrcamentoDaDespesa'
				despesas.each{|orcd| orcd.update_column(:arquivo_id, arquivo.id)}
			end
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gera_arquivo_de_elementos_da_despesa_por_projetos_e_atividades(arquivo)
		#nome_do_arquivo = "EP" + exercicio_e_mes_de_geracao + ".ORC"
		#arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		unless self.aprovacao_loa?
			alteracoes_orcamentarias_destino = Contabilidade::DotacaoDestino.joins(solicitacao_de_alteracao_orcamentaria: :decreto).where("contabilidade_decretos.data_da_legislacao >= ? AND contabilidade_decretos.data_da_legislacao < ? and contabilidade_solicitacao_de_alteracao_orcamentarias.status = 4 and contabilidade_solicitacao_de_alteracao_orcamentarias.tipo_de_credito in (1,2) and origem_do_recurso in (0, 2, 3, 5)", data_referencia, data_referencia + 1.months).all
			alteracoes_orcamentarias_destino.each do |alteracao_orcamentaria|
			arquivo.conteudo << alteracao_orcamentaria.to_sim_elementos
			arquivo.conteudo << "\r\n"
			end
		else
			orcamento.programas_de_governo.each do |programa|
				programa.orcamentos_da_despesa.where('valor > 0').each do |orcd|
					arquivo.conteudo << orcd.to_sim_elementos
					arquivo.conteudo << "\r\n"
				end
			end
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gera_arquivo_de_orcamento_das_despesas_por_projetos(arquivo)
		#nome_do_arquivo = "PA" + exercicio_e_mes_de_geracao + ".ORC"
		#arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		orgaos_ids = Loa::Orgao.where(orcamento_id: orcamento.id).ids
		unidades_orcamentarias_ids = Loa::UnidadeOrcamentaria.where("orgao_id in (?)", orgaos_ids).ids

		subacoes = Loa::Subacao.where("(data_de_envio_ao_sim between ? and ? ) and arquivo_id is null and unidade_orcamentaria_id in (?)", data_referencia, data_referencia.end_of_month, unidades_orcamentarias_ids).all
		subacoes.each do |subacao|
			arquivo.conteudo << subacao.to_sim
			arquivo.conteudo << "\r\n"
			arquivo.classe = 'Loa::Subacao'
			subacao.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_arquivo_de_unidades_orcamentarias(arquivo)
		#nome_do_arquivo = "UO" + exercicio_e_mes_de_geracao + ".BAS"
		#arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		orgaos_ids = Loa::Orgao.where(orcamento_id: orcamento.id).all.ids
		unidades_orcamentarias = Loa::UnidadeOrcamentaria.where("arquivo_id is null and orgao_id in (?) AND data_de_inclusao <= ?", orgaos_ids, data_referencia.end_of_month).all
		if unidades_orcamentarias.present?
			unidades_orcamentarias.each do |unidade|
				arquivo.conteudo << unidade.to_sim
				arquivo.conteudo << "\r\n"
				arquivo.classe = 'Loa::UnidadeOrcamentaria'
				unidade.update_column(:arquivo_id, arquivo.id)
			end
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	# LICITAÇÂO
	def existem_dados_da_licitacao_a_serem_enviados
		if self.licitacao?
			processos_ids = Licitacao::Projeto.homologado.where(envia_pro_sim: true).where('licitacao_projetos.data_de_envio_pro_sim >= ?', data_referencia).where('licitacao_projetos.data_de_envio_pro_sim < ?', data_referencia + 1.months).where("licitacao_projetos.arquivo_id is null").distinct.ids
			publicacoes_ids = Licitacao::Publicacao.joins(:projeto).where(licitacao_projetos: {status: Licitacao::Projeto.status[:homologado], arquivo_id: nil, envia_pro_sim: true}).where('licitacao_projetos.data_de_envio_pro_sim >= ?', data_referencia).where('licitacao_projetos.data_de_envio_pro_sim < ?', data_referencia + 1.months).where("licitacao_publicacoes.arquivo_id is null").distinct.ids
			comissoes_ids = Licitacao::Comissao.joins(:projetos).where('licitacao_projetos.data_de_envio_pro_sim >= ?', data_referencia).where('licitacao_projetos.data_de_envio_pro_sim < ?', data_referencia + 1.months).where("licitacao_comissoes.arquivo_id is null").distinct.ids
			membros_das_comissoes = Licitacao::MembroDaComissao.joins(comissao: :projetos).where('licitacao_projetos.data_de_envio_pro_sim >= ?', data_referencia).where('licitacao_projetos.data_de_envio_pro_sim < ?', data_referencia + 1.months).where("licitacao_membros_da_comissao.arquivo_id is null").distinct.ids
			dotacoes_ids = Licitacao::OrcamentoDaDespesaPorProjeto.joins(:projeto).where(licitacao_projetos: {status: Licitacao::Projeto.status[:homologado], arquivo_id: nil, envia_pro_sim: true}).where("licitacao_orcamentos_da_despesa_por_projetos.arquivo_id is null").where('licitacao_projetos.data_de_envio_pro_sim >= ?', data_referencia).where('licitacao_projetos.data_de_envio_pro_sim < ?', data_referencia + 1.months).distinct.ids
			contratos_ids = orcamento.contratos.where(envia_pro_sim: true, status: [Licitacao::Contrato.status["fechado"], Licitacao::Contrato.status["rescindido"]]).where("licitacao_contratos.arquivo_id is null").where('licitacao_contratos.data_de_envio_pro_sim >= ?', data_referencia).where('licitacao_contratos.data_de_envio_pro_sim < ?', data_referencia + 1.months).distinct.ids
			aditivos_ids = orcamento.aditivos.confirmados.where(envia_pro_sim: true).where("licitacao_aditivos.arquivo_id is null").where('licitacao_aditivos.data_de_envio_pro_sim >= ?', data_referencia).where('licitacao_aditivos.data_de_envio_pro_sim < ?', data_referencia + 1.months).distinct.ids
			contratados_ids = orcamento.contratados.joins(:contrato).where(licitacao_contratos: {status: [Licitacao::Contrato.status["fechado"], Licitacao::Contrato.status["rescindido"]]}).where("licitacao_contratados.arquivo_id is null").where('licitacao_contratos.data_de_envio_pro_sim >= ?', data_referencia).where('licitacao_contratos.data_de_envio_pro_sim < ?', data_referencia + 1.months).distinct.ids

			pessoa_do_projeto_ids = []
			Licitacao::ConfiguracaoSimDoProjeto.where('arquivo_id is null').where('data_de_envio >= ? AND data_de_envio < ?', data_referencia, data_referencia + 1.months).each do |configuracao_sim|
				processo_id = configuracao_sim.projeto_id
				Licitacao::PessoaDoProjeto.joins(:projeto).where.not(licitacao_projetos: {modalidade_do_processo: Licitacao::Projeto.modalidades_do_processo[:parceria_osc] }).where(licitacao_projetos: {status: Licitacao::Projeto.status[:homologado], envia_pro_sim: true}).where("licitacao_pessoas_do_projeto.arquivo_id is null").where('licitacao_projetos.id = ?', processo_id).distinct.all.each do |pessoa|
					pessoa_do_projeto_ids << pessoa.id
				end
			end
			licitantes_ids = Licitacao::PessoaDoProjeto.where('id in (?)', pessoa_do_projeto_ids).distinct.ids

			itens_do_lote_ids = []
			Licitacao::ConfiguracaoSimDoProjeto.where('arquivo_id is null').where('data_de_envio >= ? AND data_de_envio < ?', data_referencia, data_referencia + 1.months).each do |configuracao_sim|
				processo_id = configuracao_sim.projeto_id
				Licitacao::ItemDoLote.itens_dos_lotes_ativos.joins(lote: :processo).where.not(licitacao_projetos: {modalidade_do_processo: Licitacao::Projeto.modalidades_do_processo[:parceria_osc] }).where(licitacao_projetos: {status: Licitacao::Projeto.status[:homologado], envia_pro_sim: true}).where("licitacao_itens_do_lote.arquivo_id is null").where('licitacao_projetos.id = ?', processo_id).each do |item|
					itens_do_lote_ids << item.id
				end
			end
			itens_dos_lotes_dos_processos_ids = Licitacao::ItemDoLote.where('id in (?)', itens_do_lote_ids).distinct.ids

			unless processos_ids.size > 0 || publicacoes_ids.size > 0 || comissoes_ids.size > 0 || membros_das_comissoes.size > 0 || licitantes_ids.size > 0 || itens_dos_lotes_dos_processos_ids.size > 0 ||
				dotacoes_ids.size > 0 || contratos_ids.size > 0 || aditivos_ids.size > 0 || contratados_ids.size > 0
				errors[:tipo ] << "no momento não existem dados a enviar para o tipo selecionado."
			end
		end
	end

	def gera_arquivo_processos(arquivo)
		# nome_do_arquivo = "LI" + exercicio_e_mes_de_geracao + ".LCO"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")
		processos = Tcm::Lote.retorna_processos(data_referencia, poder_associado)
		processos.each do |processo|
			arquivo.conteudo << processo.to_sim
			arquivo.conteudo << "\r\n"
			arquivo.classe = processo.class.name
			processo.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gera_arquivo_processos_parcerias(arquivo)
		# nome_do_arquivo = "PC" + exercicio_e_mes_de_geracao + ".OSC"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		processos = Tcm::Lote.retorna_processos_parcerias(data_referencia, poder_associado)
		processos.each do |processo|
			arquivo.conteudo << processo.to_sim
			arquivo.conteudo << exercicio_e_mes_de_geracao << "\r\n"
			arquivo.classe = processo.class.name
			processo.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gera_arquivo_publicacoes_de_processos(arquivo)
		# nome_do_arquivo = "PE" + exercicio_e_mes_de_geracao + ".LCO"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		publicacoes = Tcm::Lote.retorna_publicacoes_de_processos(data_referencia, poder_associado)
		publicacoes.each do |publicacao|
			arquivo.conteudo << publicacao.to_sim
			arquivo.conteudo << exercicio_e_mes_de_geracao << "\r\n"
			arquivo.classe = publicacao.class.name
			publicacao.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gera_arquivo_publicacoes_de_processos_parcerias(arquivo)
		# nome_do_arquivo = "PP" + exercicio_e_mes_de_geracao + ".OSC"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		publicacoes = Tcm::Lote.retorna_publicacoes_de_processos_parcerias(data_referencia, poder_associado)
		publicacoes.each do |publicacao|
			arquivo.conteudo << publicacao.to_sim
			arquivo.conteudo << exercicio_e_mes_de_geracao << "\r\n"
			arquivo.classe = publicacao.class.name
			publicacao.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gera_arquivo_comissoes(arquivo)
		# nome_do_arquivo = "CL" + exercicio_e_mes_de_geracao + ".LCO"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		comissoes = Tcm::Lote.retorna_comissoes(data_referencia, poder_associado)
		comissoes.each do |comissao|
			arquivo.conteudo << comissao.to_sim(data_referencia)
			arquivo.conteudo << exercicio_e_mes_de_geracao << "\r\n"
			arquivo.classe = comissao.class.name
			comissao.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gera_arquivo_comissoes_parcerias(arquivo)
		# nome_do_arquivo = "CC" + exercicio_e_mes_de_geracao + ".OSC"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		comissoes = Tcm::Lote.retorna_comissoes_parcerias(data_referencia, poder_associado)
		comissoes.each do |comissao|
			arquivo.conteudo << comissao.to_sim_parceria
			arquivo.conteudo << exercicio_e_mes_de_geracao << "\r\n"
			arquivo.classe = comissao.class.name
			comissao.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gera_arquivo_membros_das_comissoes(arquivo)
		# nome_do_arquivo = "MC" + exercicio_e_mes_de_geracao + ".LCO"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		membros_das_comissoes = Tcm::Lote.retorna_membros_das_comissoes(data_referencia, poder_associado)
		membros_das_comissoes.each do |membro_da_comissao|
			arquivo.conteudo << membro_da_comissao.to_sim
			arquivo.conteudo << exercicio_e_mes_de_geracao << "\r\n"
			arquivo.classe = membro_da_comissao.class.name
			membro_da_comissao.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gera_arquivo_membros_das_comissoes_parcerias(arquivo)
		# nome_do_arquivo = "MS" + exercicio_e_mes_de_geracao + ".OSC"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		membros_das_comissoes = Tcm::Lote.retorna_membros_das_comissoes_parcerias(data_referencia, poder_associado)
		membros_das_comissoes.each do |membro_da_comissao|
			arquivo.conteudo << membro_da_comissao.to_sim_parceria
			arquivo.conteudo << exercicio_e_mes_de_geracao << "\r\n"
			arquivo.classe = membro_da_comissao.class.name
			membro_da_comissao.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gera_arquivo_licitantes_parcerias(arquivo)
		# nome_do_arquivo = "OC" + exercicio_e_mes_de_geracao + ".OSC"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		licitantes = Tcm::Lote.retorna_licitantes_parcerias(data_referencia, poder_associado)
		licitantes.each do |licitante|
			data_referencia = orcamento.exercicio.to_s << format('%02d', Tcm::Lote.mes_de_referencias[mes_de_referencia])
			arquivo.conteudo << licitante.to_sim(data_referencia)
			arquivo.classe = licitante.class.name
			licitante.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gera_arquivo_itens_do_processo(arquivo)
		# nome_do_arquivo = "TL" + exercicio_e_mes_de_geracao + ".LCO"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		itens_dos_lotes_dos_processos = Tcm::Lote.retorna_itens_do_processo(data_referencia, poder_associado)
		data_configuracao = data_referencia
		itens_dos_lotes_dos_processos.each do |item_do_lote|
			if item_do_lote.preco_final.to_f.round(2) > 0
				arquivo.conteudo << item_do_lote.to_sim
				arquivo.conteudo << exercicio_e_mes_de_geracao << "\r\n"
				arquivo.classe = item_do_lote.class.name
				item_do_lote.update_column(:arquivo_id, arquivo.id)

				configuracao = Licitacao::ConfiguracaoSimDoProjeto.where('projeto_id = ? AND data_de_envio >= ? AND data_de_envio <= ?', item_do_lote.lote.projeto_id, data_configuracao, data_configuracao + 1.months)
				if configuracao.any?
					configuracao.first.update_column(:arquivo_id, arquivo.id.to_s)
				end
			end
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gera_arquivo_dotacoes_dos_processos(arquivo)
		# nome_do_arquivo = "DL" + exercicio_e_mes_de_geracao + ".LCO"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		dotacoes = Tcm::Lote.retorna_dotacoes_dos_processo(data_referencia, poder_associado)
		dotacoes.group_by(&:projeto).each do |projeto, dotacoes_por_projeto|
			dotacoes_por_projeto.group_by(&:funcao_programatica_do_sim).each do |funcao, dotacoes_agrupadas|
				valor_total = dotacoes_agrupadas.sum(&:valor)
				_dotacoes = [ dotacoes_agrupadas.last ]
				_dotacoes.each do |dotacao|
					arquivo.conteudo << dotacao.to_sim(valor_total)
					arquivo.conteudo << exercicio_e_mes_de_geracao << "\r\n"
					arquivo.classe = dotacao.class.name
					dotacao.update_column(:arquivo_id, arquivo.id)
				end
			end
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gera_arquivo_dotacoes_dos_processos_parcerias(arquivo)
		# nome_do_arquivo = "DC" + exercicio_e_mes_de_geracao + ".OSC"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		dotacoes = Tcm::Lote.retorna_dotacoes_dos_processo_parcerias(data_referencia, poder_associado)

		dotacoes.group_by(&:projeto).each do |projeto, dotacoes_por_projeto|
			dotacoes_por_projeto.group_by(&:funcao_programatica_do_sim).each do |funcao, dotacoes_agrupadas|
				valor_total = dotacoes_agrupadas.sum(&:valor)
				_dotacoes = [ dotacoes_agrupadas.last ]
				_dotacoes.each do |dotacao|
					arquivo.conteudo << dotacao.to_sim(valor_total)
					arquivo.conteudo << exercicio_e_mes_de_geracao << "\r\n"
					arquivo.classe = dotacao.class.name
					dotacao.update_column(:arquivo_id, arquivo.id)
				end
			end
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gera_arquivo_contratos_e_aditivos(arquivo)
		# nome_do_arquivo = "CO" + exercicio_e_mes_de_geracao + ".LCO"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		contratos = Tcm::Lote.retorna_contratos(data_referencia, poder_associado)
		contratos.each do |contrato|
			arquivo.conteudo << contrato.to_sim
			arquivo.conteudo << "\r\n"
			contrato.update_column(:arquivo_id, arquivo.id)
		end

		aditivos = Tcm::Lote.retorna_aditivos(data_referencia, poder_associado)
		aditivos.each do |aditivo|
			arquivo.conteudo << aditivo.to_sim
			arquivo.conteudo << "\r\n"
			aditivo.update_column(:arquivo_id, arquivo.id)
		end

		arquivo.classe = "Licitacao::Contrato;Licitacao::Aditivo"

		salva_ou_deleta_arquivo(arquivo)
	end

	def gera_arquivo_contratos_parcerias(arquivo)
		# nome_do_arquivo = "PS" + exercicio_e_mes_de_geracao + ".OSC"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		contratos = Tcm::Lote.retorna_contratos_parcerias(data_referencia, poder_associado)
		contratos.each do |contrato|
			arquivo.conteudo << contrato.to_sim
			arquivo.conteudo << exercicio_e_mes_de_geracao << "\r\n"
			arquivo.classe = contrato.class.name
			contrato.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gera_arquivo_aditivos_parcerias(arquivo)
		# nome_do_arquivo = "PD" + exercicio_e_mes_de_geracao + ".OSC"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		aditivos_osc = Tcm::Lote.retorna_aditivos_de_parceria_osc(data_referencia, poder_associado)
		aditivos_osc.each do |aditivo_osc|
			arquivo.conteudo << aditivo_osc.to_sim_parceria_osc
			arquivo.classe = aditivo_osc.class.name
			aditivo_osc.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gera_arquivo_contratados(arquivo)
		# nome_do_arquivo = "CT" + exercicio_e_mes_de_geracao + ".LCO"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		contratados_por_contrato = Tcm::Lote.retorna_contratados_por_contrato(data_referencia, poder_associado)
		contratados_por_contrato.each do |contratado|
			arquivo.conteudo << contratado.to_sim
			arquivo.conteudo << exercicio_e_mes_de_geracao << "\r\n"
			arquivo.classe = contratado.class.name
			contratado.update_column(:arquivo_id, arquivo.id)
		end

		contratados_por_aditivo = Tcm::Lote.retorna_contratados_por_aditivo(data_referencia, poder_associado)
		contratados_por_aditivo.each do |contratado|
			arquivo.conteudo << contratado.to_sim
			arquivo.conteudo << exercicio_e_mes_de_geracao << "\r\n"
			arquivo.classe = contratado.class.name
			contratado.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_transferencias_financeiras(arquivo)
		puts "Gerando Transferencias Financeiras"
		# nome_do_arquivo = "EF" + exercicio_e_mes_de_geracao + ".DCD"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		transferencias = Tcm::Lote.retorna_transferencias_financeiras(data_referencia, poder_associado)
		transferencias.each do |transferencia|
			arquivo.conteudo << transferencia.to_sim(exercicio_e_mes_de_geracao)
			arquivo.conteudo << exercicio_e_mes_de_geracao << "\r\n"
			arquivo.classe = transferencia.class.name
			transferencia.update_column(:arquivo_id, arquivo.id)
		end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_balancetes_de_receitas_orcamentarias_pcasp(arquivo)
		puts "Gerando Balancete de Receitas Orcamentarias PCASP"
		# nome_do_arquivo = "BE#{exercicio_e_mes_de_geracao}.BAL"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		ultima_conta = nil

		movimentacoes = ActiveRecord::Base.connection.execute("
			SELECT ccec.conta_id, cm.codigo_da_conta, cm.unidade_orcamentaria_id, cm.codigo_completo_fr, cm.ic_nr, CASE WHEN cm.ic_co in ('3110', '3120', '3210', '3220') THEN cm.ic_co ELSE '0000' END ic_co_at
			FROM contabilidade_movimentacoes_do_plano_de_contas cm
			LEFT JOIN contabilidade_contas_por_eventos_contabeis ccec ON ccec.id = cm.conta_por_evento_contabil_id
			LEFT JOIN contabilidade_taloes_de_receita tr ON cm.gerador_id = tr.id AND cm.gerador_type = 'Contabilidade::TalaoDeReceita'
			LEFT JOIN loa_orcamentos_da_receita lor ON cm.gerador_id = lor.id AND cm.gerador_type = 'Loa::OrcamentoDaReceita'
			LEFT JOIN loa_unidades_orcamentarias_por_natureza_da_receita luon ON lor.unidade_orcamentaria_por_natureza_da_receita_id = luon.id
			LEFT JOIN base_naturezas_da_receita bnr ON (bnr.id = luon.natureza_da_receita_id or bnr.id = tr.natureza_da_receita_id)
			LEFT JOIN loa_unidades_orcamentarias luo ON luo.id = cm.unidade_orcamentaria_id
			LEFT JOIN base_tipos_de_unidades_administrativas btua ON btua.id = luo.tipo_de_unidade_administrativa_id
			where data_de_lancamento <= '#{data_referencia.end_of_month.strftime('%Y/%m/%d')}' AND extract(year from data_de_lancamento) = #{data_referencia.year}
			AND (gerador_type IN ('Contabilidade::TalaoDeReceita', 'Loa::OrcamentoDaReceita'))
			and (codigo_da_conta LIKE ANY(array['5________', '6________']))
			and coalesce(cm.lancamento_manual, 0) != 1000
			#{"and btua.poder_associado = #{poder_associado}" if poder_associado.present? }
			group by ccec.conta_id, cm.codigo_da_conta, cm.unidade_orcamentaria_id, cm.codigo_completo_fr, cm.ic_nr, ic_co_at
		")

		movimentacoes.each do |movimentacao|
			conta = Contabilidade::Conta.find(movimentacao["conta_id"])
			unidade_orcamentaria = Loa::UnidadeOrcamentaria.find(movimentacao["unidade_orcamentaria_id"])
			ic_nr = movimentacao["ic_nr"]
			ic_co = movimentacao["ic_co_at"]
			outras_condicoes = []
			if unidade_orcamentaria.present?
				outras_condicoes << "unidade_orcamentaria_id = #{unidade_orcamentaria.id}"
			else
				outras_condicoes << "unidade_orcamentaria_id is null"
			end
			outras_condicoes << "base_tipos_de_unidades_administrativas.poder_associado = #{poder_associado}" if poder_associado.present?
			
			if movimentacao["codigo_completo_fr"].present?
				outras_condicoes << "contabilidade_movimentacoes_do_plano_de_contas.codigo_completo_fr = '#{movimentacao["codigo_completo_fr"]}'" 
			else
				outras_condicoes << "contabilidade_movimentacoes_do_plano_de_contas.codigo_completo_fr is null"
			end

			movimentacoes_do_periodo = conta.movimentacoes_do_plano_de_contas.joins(unidade_orcamentaria: :tipo_de_unidade_administrativa).sem_encerramento.where(
					"contabilidade_movimentacoes_do_plano_de_contas.data_de_lancamento >= ?
					AND contabilidade_movimentacoes_do_plano_de_contas.data_de_lancamento <= ?
					AND ic_nr = ? AND (CASE WHEN ic_co in ('3110', '3120', '3210', '3220') THEN ic_co ELSE '0000' END) = ?", data_referencia, data_referencia.end_of_month, ic_nr, ic_co
				).where("COALESCE(contabilidade_movimentacoes_do_plano_de_contas.lancamento_manual, 0) != 999").where("#{outras_condicoes.join(" AND ")}")

			ids_movimentacoes_dos_balancetes = movimentacoes_do_periodo.map {|m| m.movimentacoes_das_contas_do_balancete.ids}.flatten rescue nil
			
			args = {
				unidade_orcamentaria: unidade_orcamentaria,
				ic_nr: ic_nr,
				ic_co: ic_co,
				fonte_de_recursos: movimentacao["codigo_completo_fr"],
				mes_de_referencia: read_attribute_before_type_cast(:mes_de_referencia),
				saldo_inicial_do_mes: Contabilidade::BalanceteDeVerificacao.saldo_inicial_da_conta_baseado_no_mes(conta, data_referencia.end_of_month, unidade_orcamentaria, poder_associado, nil, ic_nr, nil, movimentacao["codigo_completo_fr"]),
				saldo_debito_total: Contabilidade::BalanceteDeVerificacao.valor_total_debitos(ids_movimentacoes_dos_balancetes),
				saldo_credito_total: Contabilidade::BalanceteDeVerificacao.valor_total_creditos(ids_movimentacoes_dos_balancetes)
			}

			arquivo.conteudo << conta.to_sim_receita(args)
			arquivo.conteudo << "\r\n"
		end

		# if ultima_conta != conta
		# 	ultima_conta = conta
		# 	Contabilidade::EnvioAoconta_por_evento_contabil_idSimPorObjeto.find_or_create_by(arquivo_id: arquivo.id, objeto_id: conta.id, objeto_type: conta.class.name)
		# end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gerar_balancetes_de_despesas_orcamentarias_pcasp(arquivo)
		puts "Gerando Balancete de Despesas Orcamentarias PCASP"
		# nome_do_arquivo = "BA#{exercicio_e_mes_de_geracao}.BAL"
		# arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

		movimentacoes = ActiveRecord::Base.connection.execute("
			SELECT ccec.conta_id, cm.codigo_da_conta, luo.unidade_gestora_id, cm.unidade_orcamentaria_id, cm.codigo_completo_fr, 
			bf.id as funcao_id, bsf.id as subfuncao_id, lpg.id as programa_de_governo_id, la.id as acao_id, ls.id as subacao_id, 
			LEFT(cm.ic_nd, 6) AS ic_nd,
			CASE WHEN cm.ic_co in ('3110', '3120', '3210', '3220') THEN cm.ic_co ELSE '0000' END ic_co_at
			FROM contabilidade_movimentacoes_do_plano_de_contas cm
			LEFT JOIN contabilidade_pagamentos cp ON cm.gerador_id = cp.id AND cm.gerador_type = 'Contabilidade::Pagamento'
			LEFT JOIN contabilidade_contas_por_eventos_contabeis ccec ON ccec.id = cm.conta_por_evento_contabil_id
			LEFT JOIN contabilidade_liquidacoes cl ON cl.id = cp.liquidacao_id
			LEFT JOIN contabilidade_empenhos ce ON ce.id = cl.empenho_id
			LEFT JOIN loa_orcamentos_da_despesa lod ON (lod.id = ce.orcamento_da_despesa_id or (cm.gerador_id = lod.id AND cm.gerador_type = 'Loa::OrcamentoDaDespesa'))
			LEFT JOIN loa_elementos_de_despesa_por_subacao leds ON leds.id = lod.elemento_de_despesa_por_subacao_id
			LEFT JOIN loa_subacoes ls ON ls.id = leds.subacao_id
			LEFT JOIN loa_acoes la ON la.id = ls.acao_id
			LEFT JOIN loa_programas_de_governo lpg ON lpg.id = la.programa_de_governo_id
			LEFT JOIN base_funcoes bf ON bf.id = ls.funcao_id
			LEFT JOIN base_subfuncoes bsf on bsf.id = ls.subfuncao_id
			LEFT JOIN loa_unidades_orcamentarias luo ON luo.id = cm.unidade_orcamentaria_id
			LEFT JOIN base_tipos_de_unidades_administrativas btua ON btua.id = luo.tipo_de_unidade_administrativa_id 
			where data_de_lancamento <= '#{data_referencia.end_of_month.strftime('%Y/%m/%d')}' AND extract(year from data_de_lancamento) = #{data_referencia.year}
			AND (gerador_type IN ('Contabilidade::Pagamento', 'Loa::OrcamentoDaDespesa'))
			and (codigo_da_conta LIKE ANY(array['5________', '6________']))
			and cm.ic_nd is not null
			and coalesce(cm.lancamento_manual, 0) != 1000
			#{"and btua.poder_associado = #{poder_associado}" if poder_associado.present? }
			group by ccec.conta_id, cm.codigo_da_conta, cm.unidade_orcamentaria_id, luo.unidade_gestora_id, cm.codigo_completo_fr,
			bf.id, bsf.id, lpg.id, la.id, ls.id, LEFT(cm.ic_nd, 6), ic_co_at
			order by ccec.conta_id, cm.codigo_da_conta, luo.unidade_gestora_id, cm.codigo_completo_fr,
			bf.id, bsf.id, lpg.id, la.id, ls.id, LEFT(cm.ic_nd, 6), ic_co_at
		")

		movimentacoes.each do |movimentacao|
			conta = Contabilidade::Conta.find(movimentacao["conta_id"])
			unidade_orcamentaria = Loa::UnidadeOrcamentaria.find(movimentacao["unidade_orcamentaria_id"])

			funcao = Base::Funcao.find(movimentacao["funcao_id"])
			subfuncao = Base::Subfuncao.find(movimentacao["subfuncao_id"])
			subacao = Loa::Subacao.find(movimentacao["subacao_id"])
			acao = Loa::Acao.find(movimentacao["acao_id"])
			programa_de_governo = Loa::ProgramaDeGoverno.find(movimentacao["programa_de_governo_id"])
			ic_nd = movimentacao["ic_nd"]
			ic_co = movimentacao["ic_co_at"]

			outras_condicoes = []

			if unidade_orcamentaria.present?
				outras_condicoes << "unidade_orcamentaria_id = #{unidade_orcamentaria.id}"
			else
				outras_condicoes << "unidade_orcamentaria_id is null"
			end
			outras_condicoes << "base_tipos_de_unidades_administrativas.poder_associado = #{poder_associado}" if poder_associado.present?
			if movimentacao["codigo_completo_fr"].present?
				outras_condicoes << "contabilidade_movimentacoes_do_plano_de_contas.codigo_completo_fr = '#{movimentacao["codigo_completo_fr"]}'"
			else
				outras_condicoes << "contabilidade_movimentacoes_do_plano_de_contas.codigo_completo_fr is null"
			end

			movimentacoes_query = conta.movimentacoes_do_plano_de_contas.joins(unidade_orcamentaria: :tipo_de_unidade_administrativa).sem_encerramento.where("gerador_type IN ('Contabilidade::Pagamento', 'Loa::OrcamentoDaDespesa')")

			movimentacoes_do_periodo_anterior = movimentacoes_query
				.where("LEFT(ic_nd, 6) = ? and (CASE WHEN ic_co in ('3110', '3120', '3210', '3220') THEN ic_co ELSE '0000' END) = ? and contabilidade_movimentacoes_do_plano_de_contas.data_de_lancamento < ? AND extract(year from data_de_lancamento) = ?", ic_nd, ic_co, data_referencia, data_referencia.year)
				.where("#{outras_condicoes.join(" AND ")}")

			movimentacoes_do_periodo = movimentacoes_query.where(
					"contabilidade_movimentacoes_do_plano_de_contas.data_de_lancamento >= ?
					AND contabilidade_movimentacoes_do_plano_de_contas.data_de_lancamento <= ? AND LEFT(ic_nd, 6) = ? AND (CASE WHEN ic_co in ('3110', '3120', '3210', '3220') THEN ic_co ELSE '0000' END) = ?", data_referencia, data_referencia.end_of_month, ic_nd, ic_co
			).where("COALESCE(contabilidade_movimentacoes_do_plano_de_contas.lancamento_manual, 0) != 999").where("#{outras_condicoes.join(" AND ")}")

			movimentacoes_do_periodo = movimentacoes_do_periodo.select do |i|
				if i.gerador_type == 'Contabilidade::Pagamento'
					sub_acao = i.gerador.liquidacao.empenho.orcamento_da_despesa.elemento_de_despesa_por_subacao.subacao
				elsif i.gerador_type == 'Loa::OrcamentoDaDespesa'
					sub_acao = i.gerador.elemento_de_despesa_por_subacao.subacao
				end

				sub_acao && sub_acao == subacao && sub_acao.acao == acao && sub_acao.acao.programa_de_governo == programa_de_governo && sub_acao.funcao == funcao && sub_acao.subfuncao == subfuncao
			end

			ids_movimentacoes_dos_balancetes = movimentacoes_do_periodo.flatten.compact.map {|m| m.movimentacoes_das_contas_do_balancete.ids}.flatten rescue nil

			args = {
				mes_de_referencia: read_attribute_before_type_cast(:mes_de_referencia),
				conta: conta,
				unidade_orcamentaria: unidade_orcamentaria,
				fonte_de_recursos: movimentacao["codigo_completo_fr"],
				funcao: funcao,
				subfuncao: subfuncao,
				subacao: subacao,
				acao: subacao.acao,
				programa_de_governo: subacao.acao.programa_de_governo,
				ic_nd: ic_nd,
				ic_co: ic_co,
				saldo_inicial_do_mes: Contabilidade::BalanceteDeVerificacao.calcula_saldo_inicial_da_conta_baseado_no_mes(conta, movimentacoes_do_periodo_anterior),
				saldo_debito_total: Contabilidade::BalanceteDeVerificacao.valor_total_debitos(ids_movimentacoes_dos_balancetes),
				saldo_credito_total: Contabilidade::BalanceteDeVerificacao.valor_total_creditos(ids_movimentacoes_dos_balancetes)
			}

			arquivo.conteudo << args[:conta].to_sim_despesa(args)
			arquivo.conteudo << "\r\n"
		end

		# if ultima_conta != conta
		# 	ultima_conta = conta
		# 	Contabilidade::EnvioAoSimPorObjeto.find_or_create_by(arquivo_id: arquivo.id, objeto_id: conta.id, objeto_type: conta.class.name)
		# end

		salva_ou_deleta_arquivo(arquivo)
	end

	def gera_bens_patrimoniais(arquivo)
		puts "Gerando Bens Patrimoniais"
		# nome_do_arquivo = "BP#{exercicio_e_mes_de_geracao}.PAT"
		self.gera_arquivo(arquivo, tipo_de_poder, "arquivo_id")
	end

	def gera_bens_patrimoniais_por_unidade(arquivo)
		puts "Gerando Bens por Unidade"
		# nome_do_arquivo = "BO#{exercicio_e_mes_de_geracao}.PAT"
		self.gera_arquivo(arquivo, tipo_de_poder, "arquivo_por_unidade_id", "BemPatrimonial::PorUnidade")
	end

	def gera_bens_por_empenho(arquivo)
		puts "Gerando Bens por Empenho"
		# nome_do_arquivo = "BN#{exercicio_e_mes_de_geracao}.PAT"
		self.gera_arquivo(arquivo, tipo_de_poder, "arquivo_por_empenho_id", "BemPatrimonial::PorEmpenho")
	end

	def gera_ajuste_reavaliacao_patrimonial(arquivo)
		puts "Gerando Ajuste/Reavaliação Patrimonial"
		# nome_do_arquivo = "RB#{exercicio_e_mes_de_geracao}.PAT"
		self.gera_arquivo(arquivo, tipo_de_poder, "arquivo_id")
	end

	def gera_contas_redutoras_patrimonial(arquivo)
		puts "Gerando Conta Redutora Patrimonial"
		# nome_do_arquivo = "RP#{exercicio_e_mes_de_geracao}.PAT"
		self.gera_arquivo(arquivo, tipo_de_poder, "arquivo_contas_id", "MovimentacaoFinanceiraDoBem::ContasRedutoras")
	end

	# def gera_reavaliacao_patrimonial_e_contas_redutoras_agrupadas
	# 	nome_do_arquivo = "RB#{exercicio_e_mes_de_geracao}.PAT"
	# 	arquivo = Tcm::Arquivo.create(nome: nome_do_arquivo, lote_id: id, conteudo: "")

	# 	nome_do_arquivo_2 = "RP#{exercicio_e_mes_de_geracao}.PAT"
	# 	arquivo_2 = Tcm::Arquivo.create(nome: nome_do_arquivo_2, lote_id: id, conteudo: "")

	# 	movimentos_dos_bens = Tcm::Lote.retorna_ajuste_reavaliacao_patrimonial(data_referencia, poder_associado)

	# 	movimentos_dos_bens.group_by{|movimento| [movimento.bem_patrimonial, movimento.situacao]}.each do |criterios, movimentos|
	# 		movimento = movimentos.sort_by(&:data_da_movimentacao).last
	# 		total = movimentos.inject(0) {|total, movimento| total + movimento.valor_da_operacao.to_d}

	# 		arquivo.conteudo << movimento.to_sim_ajuste_reavaliacao_patrimonial_temporaria(data_referencia, total.abs)
	# 		arquivo.conteudo << "\r\n"
	# 		arquivo.classe = movimento.class.name
	# 		movimentos.each{|mov| mov.update_column(:arquivo_id, arquivo.id)}
	# 	end

	# 	movimentos_dos_bens.group_by{|movimento| [movimento.bem_patrimonial, movimento.situacao_sim]}.each do |criterios, movimentos|
	# 		movimento = movimentos.sort_by(&:data_da_movimentacao).last
	# 		total = movimentos.inject(0) {|total, movimento| total + movimento.valor_da_operacao.to_d}

	# 		arquivo_2.conteudo << movimento.to_sim_contas_redutoras_dos_bens_temporario(data_referencia, total.abs)
	# 		arquivo_2.conteudo << "\r\n"
	# 		arquivo_2.classe = 'MovimentacaoFinanceiraDoBem::ContasRedutoras'
	# 		movimentos.each{|mov| mov.update_column(:arquivo_contas_id, arquivo_2.id)}
	# 	end

	# 	salva_ou_deleta_arquivo(arquivo)
	# 	salva_ou_deleta_arquivo(arquivo_2)
	# end

	##CONSULTAS DA CONTABILIDADE
	def retorna_unidades_gestoras(poder_associado)
		if self.mes_de_referencia == "janeiro"
			orcamento.unidades_gestoras.joins(unidades_orcamentarias: :tipo_de_unidade_administrativa).where('base_tipos_de_unidades_administrativas.poder_associado = ?', poder_associado).distinct.all
		else
			orcamento.unidades_gestoras.joins(unidades_orcamentarias: :tipo_de_unidade_administrativa).where('loa_unidades_gestoras.arquivo_id is null AND base_tipos_de_unidades_administrativas.poder_associado = ?', poder_associado).distinct.all
		end
	end

	def retorna_contas_extras(data_referencia, poder_associado)
		contas_do_orc = orcamento.contas_extra_por_unidades_orcamentarias
			.joins(unidade_orcamentaria: :tipo_de_unidade_administrativa)
			.joins(:conta_extra_orcamentaria)
			.where('contabilidade_contas_extra_por_unidades_orcamentarias.arquivo_id IS NULL')
			.where('base_tipos_de_unidades_administrativas.poder_associado = ?', poder_associado)

		ids = contas_do_orc.select do |conta|
			receita_primeira_data = conta.receitas_extras_da_conta_extra_por_uo.order('data_do_talao ASC').first&.data_do_talao
			despesa_primeira_data = conta.despesas_extras_da_conta_extra_por_uo.order('data_de_emissao ASC').first&.data_de_emissao

			(receita_primeira_data && receita_primeira_data.between?(data_referencia, data_referencia.end_of_month)) ||
			(despesa_primeira_data && despesa_primeira_data.between?(data_referencia, data_referencia.end_of_month)) ||
			(conta.conta_extra_orcamentaria.repasse_duodecimo_para_a_camara? && self.mes_de_referencia == 'janeiro')
		end.map(&:id)

		return contas_do_orc.where(id: ids)
	end

	def retorna_alocacoes_de_recurso
		orcamento.alocacoes_de_recurso_de_rpps.distinct.all
	end

	def self.retorna_gestores (data, poder_associado, contexto_atual)
		gestores = []

		if data.month == 1
			Loa::UnidadeGestora.find_by_sql("SELECT DISTINCT ug.* FROM loa_gestores gestor INNER JOIN loa_unidades_gestoras ug ON ug.id = gestor.unidade_gestora_id INNER JOIN loa_unidades_orcamentarias uo ON uo.unidade_gestora_id = ug.id INNER JOIN loa_orgaos org ON org.id = uo.orgao_id INNER JOIN orcamentos orc ON orc.id = org.orcamento_id INNER JOIN base_tipos_de_unidades_administrativas tipo_unid ON tipo_unid.id = uo.tipo_de_unidade_administrativa_id WHERE orc.exercicio = #{data.year} AND tipo_unid.poder_associado = #{poder_associado}").each do |ug|
				gestor = ug.gestores.atual_na_data(data.end_of_month) rescue nil
				gestores << gestor if gestor.present?
			end
		else
			gestores = Loa::Gestor.joins(unidade_gestora: [unidades_orcamentarias:[orgao: :tipo_de_unidade_administrativa]]).where('loa_gestores.arquivo_id IS NULL AND loa_gestores.inicio_da_gestao BETWEEN ? AND ? AND base_tipos_de_unidades_administrativas.poder_associado = ? AND loa_orgaos.orcamento_id = ?', data, data.end_of_month, poder_associado, contexto_atual.id).distinct.all
		end

		return gestores
	end

	def self.retorna_ordenadores_de_despesa (data, poder_associado, contexto_atual =  nil)
		ordenadores = []

		if data.month == 1
			Loa::UnidadeOrcamentaria.find_by_sql("SELECT uo.* FROM loa_unidades_orcamentarias uo INNER JOIN loa_orgaos org ON org.id = uo.orgao_id INNER JOIN orcamentos orc ON orc.id = org.orcamento_id INNER JOIN base_tipos_de_unidades_administrativas tipo_unid ON tipo_unid.id = uo.tipo_de_unidade_administrativa_id WHERE orc.exercicio = #{data.year} AND tipo_unid.poder_associado = #{poder_associado}").each do |uo|
				ordenador = uo.ordenadores_de_despesa.atual_na_data(data.end_of_month) rescue nil
				ordenadores << ordenador if ordenador.present?
			end
		else
			ordenadores = Loa::OrdenadorDeDespesa.joins(unidade_orcamentaria: :tipo_de_unidade_administrativa).joins(unidade_orcamentaria: :orgao).where('loa_ordenadores_de_despesa.arquivo_id is null AND loa_ordenadores_de_despesa.data_inicio_da_gestao BETWEEN ? AND ? AND base_tipos_de_unidades_administrativas.poder_associado = ? AND loa_orgaos.orcamento_id = ?', data, data.end_of_month, poder_associado, contexto_atual.id).distinct.all
		end

		return ordenadores
	end

	def retorna_balancetes_de_despesas_orcamentarias (data, poder_associado)
		Loa::OrcamentoDaDespesa.joins(elemento_de_despesa_por_subacao:[subacao:[unidade_orcamentaria: :tipo_de_unidade_administrativa]]).joins("left join orcamentos on base_tipos_de_unidades_administrativas.modulo_id = orcamentos.id").where('orcamentos.exercicio = ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', data.year, poder_associado).distinct.all
	end

	def self.retorna_balancetes_de_recitas_orcamentarias (data, poder_associado)
		Loa::OrcamentoDaReceita.joins(unidade_orcamentaria_por_natureza_da_receita:[unidade_orcamentaria: :tipo_de_unidade_administrativa]).joins("left join orcamentos on base_tipos_de_unidades_administrativas.modulo_id = orcamentos.id").where('orcamentos.exercicio = ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', data.year, poder_associado).distinct.all
	end

	def self.retorna_liquidacoes_sem_marcacao (data, poder_associado)
		#status das a serem comparadados são: confirmado(2), enviado_ao_financeiro(5), recebido_pelo_financeiro(6) e autorizado (8)
		liquidacoes = Contabilidade::Liquidacao.joins(empenho: [unidade_orcamentaria: :tipo_de_unidade_administrativa]).where(
			'contabilidade_liquidacoes.data_da_liquidacao >= ? AND contabilidade_liquidacoes.data_da_liquidacao < ? AND base_tipos_de_unidades_administrativas.poder_associado = ? 
			AND contabilidade_liquidacoes.status in (2,5,6,8) AND ((contabilidade_liquidacoes.restos_a_pagar = false AND contabilidade_liquidacoes.orcamento_id = ?) OR contabilidade_liquidacoes.restos_a_pagar = true)',data, data + 1.months, poder_associado, Orcamento.find_by(exercicio: data.year)).distinct.all

		return liquidacoes
	end

	def retorna_parcelamentos_do_rpps(data)
		orcamento.parcelamentos_do_rpps.where('contabilidade_parcelamentos_do_rpps.arquivo_id is null').distinct.all
	end

	def retorna_acompanhamentos_de_parcelamentos_do_rpps (data)
		Contabilidade::AcompanhamentoDeParcelamentoDoRpps.joins(:parcelamento_do_rpps).where('contabilidade_acompanhamentos_de_parcelamento_do_rpps.arquivo_id is null AND contabilidade_acompanhamentos_de_parcelamento_do_rpps.data_do_pagamento >= ? AND contabilidade_acompanhamentos_de_parcelamento_do_rpps.data_do_pagamento < ?', data, data + 1.months).distinct.all
	end

	def retorna_pagamentos (data, poder_associado)
		orcamentos_das_despesas_ids = retorna_balancetes_de_despesas_orcamentarias(data, poder_associado).pluck(:id)
		orcamento.pagamentos.joins(liquidacao: [empenho: [orcamento_da_despesa:[elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]]]).where('contabilidade_pagamentos.arquivo_id is null AND contabilidade_pagamentos.status not in (1) AND contabilidade_pagamentos.data >= ? AND contabilidade_pagamentos.data < ? AND base_tipos_de_unidades_administrativas.poder_associado = ? ', data, data + 1.months, poder_associado).distinct.all
	end

	def retorna_pagamentos_de_folha (data, poder_associado)
		orcamento.pagamentos.joins(liquidacao: [empenho: [orcamento_da_despesa:[elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]]]).where('contabilidade_pagamentos.arquivo_de_folha_id is null AND contabilidade_liquidacoes.data_de_emissao_da_folha is not null 
			AND contabilidade_pagamentos.data >= ? AND contabilidade_pagamentos.data < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', data, data + 1.months, poder_associado).distinct.all
	end

	def retorna_pagamentos_para_cheque (data, poder_associado)
		orcamento.pagamentos.joins(liquidacao: [empenho: [orcamento_da_despesa:[elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]]]).where(
			'contabilidade_pagamentos.arquivo_de_cheque_id is null AND contabilidade_pagamentos.data >= ? AND contabilidade_pagamentos.data < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', data, data + 1.months, poder_associado).distinct.all
	end

	def self.retorna_deducoes_de_notas_de_pagamento (data, poder_associado)
		Contabilidade::Retencao.joins(pagamento: [liquidacao: [empenho: [orcamento_da_despesa:[elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]]]]).where(
			'contabilidade_retencoes.arquivo_id is null AND contabilidade_pagamentos.data >= ? AND contabilidade_pagamentos.data < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', data, data + 1.months, poder_associado).distinct.all
	end

	def self.retorna_notas_fiscais (data, poder_associado)
		liquidacoes_ids =  Orcamento.find_by(exercicio: data.year).liquidacoes.where('contabilidade_liquidacoes.status in (2,5,6,8)').pluck(:id)

		notas_fiscais = Contabilidade::NotaFiscal.joins(liquidacao: [empenho: [orcamento_da_despesa:[elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]]]).where('contabilidade_notas_fiscais.arquivo_id is null AND contabilidade_liquidacoes.data_da_liquidacao is not null AND contabilidade_notas_fiscais.tipo_de_emissao is not null
			AND contabilidade_liquidacoes.status in (2,5,6,8) and tipo_da_nota between 1 and 6 AND contabilidade_liquidacoes.id in (?) AND contabilidade_liquidacoes.data_da_liquidacao >= ? AND contabilidade_liquidacoes.data_da_liquidacao < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?',liquidacoes_ids, data, data + 1.months, poder_associado)

		notas_fiscais_de_rp = Contabilidade::NotaFiscal.joins(liquidacao: [empenho: [orcamento_da_despesa:[elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]]]).where('contabilidade_notas_fiscais.arquivo_id is null AND contabilidade_liquidacoes.data_da_liquidacao is not null AND contabilidade_notas_fiscais.tipo_de_emissao is not null
			AND contabilidade_liquidacoes.status in (2,5,6,8) and tipo_da_nota between 1 and 6 AND contabilidade_liquidacoes.restos_a_pagar is true AND contabilidade_liquidacoes.data_da_liquidacao >= ? AND contabilidade_liquidacoes.data_da_liquidacao < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', data, data + 1.months, poder_associado)
		
		notas_fiscais.merge(notas_fiscais_de_rp)
		return notas_fiscais
	end

	def self.retorna_itens_das_notas (data, poder_associado)
		liquidacoes_id = Orcamento.find_by(exercicio: data.year).liquidacoes.joins(:nota_fiscal).where('contabilidade_liquidacoes.status in (2,5,6,8) and contabilidade_notas_fiscais.tipo_da_nota between 1 and 6').pluck(:id)

		itens = Contabilidade::ItemDaNotaFiscal.joins(liquidacao: [empenho: [orcamento_da_despesa:[elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]]]).where('contabilidade_itens_da_nota_fiscal.arquivo_id is null AND contabilidade_liquidacoes.data_da_liquidacao is not null AND contabilidade_itens_da_nota_fiscal.liquidacao_id in (?) AND contabilidade_liquidacoes.status in (2,5,6,8)AND contabilidade_liquidacoes.data_da_liquidacao >= ? AND contabilidade_liquidacoes.data_da_liquidacao < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', liquidacoes_id, data, data + 1.months, poder_associado).distinct.all

		itens_de_rp = Contabilidade::ItemDaNotaFiscal.joins(liquidacao: :nota_fiscal).joins(liquidacao: [empenho: [orcamento_da_despesa:[elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]]]).where('contabilidade_itens_da_nota_fiscal.arquivo_id is null AND contabilidade_liquidacoes.data_da_liquidacao is not null AND contabilidade_liquidacoes.restos_a_pagar is true AND contabilidade_liquidacoes.data_da_liquidacao >= ? AND contabilidade_liquidacoes.data_da_liquidacao < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', data, data + 1.months, poder_associado).distinct.all
		
		itens.merge(itens_de_rp)
		return itens
	end

	def self.retorna_estornos_de_liquidacao (data, poder_associado)
		Contabilidade::EstornoDeLiquidacao.joins(liquidacao: [empenho: [orcamento_da_despesa:[elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]]]).where(
			'contabilidade_estornos_de_liquidacao.arquivo_id is null AND contabilidade_estornos_de_liquidacao.data_do_estorno >= ? AND contabilidade_estornos_de_liquidacao.data_do_estorno < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', data, data + 1.months, poder_associado).distinct.all
	end

	def self.retorna_estornos_de_pagamento (data, poder_associado)
		Contabilidade::EstornoDePagamento.joins(pagamento: [liquidacao: [empenho: [orcamento_da_despesa:[elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]]]]).where(
			'contabilidade_estornos_de_pagamento.arquivo_id is null AND contabilidade_estornos_de_pagamento.data_do_estorno >= ? AND contabilidade_estornos_de_pagamento.data_do_estorno < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', data, data + 1.months, poder_associado).distinct.all
	end

	def self.retorna_despesas_extra (data, poder_associado)
		Contabilidade::DespesaExtraOrcamentaria.joins(unidade_orcamentaria: :tipo_de_unidade_administrativa).where('contabilidade_despesas_extra_orcamentarias.arquivo_id is null AND 
			contabilidade_despesas_extra_orcamentarias.data_de_emissao >= ? AND contabilidade_despesas_extra_orcamentarias.data_de_emissao < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', data, data + 1.months, poder_associado).distinct.all
	end

	def self.retorna_balancetes_de_despesas_e_receita_extra_orcamentarias (data, poder_associado)
		Contabilidade::ContaExtraPorUnidadeOrcamentaria.joins(:conta_extra_orcamentaria).joins(unidade_orcamentaria: :tipo_de_unidade_administrativa).where('contabilidade_contas_extra_orcamentarias.orcamento_id = ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', Orcamento.find_by(exercicio: data.year), poder_associado).distinct.all
	end

	def self.retorna_estorno_de_despesas_extra (data,poder_associado)
		Contabilidade::EstornoDeDespesaExtraOrcamentaria.joins(despesa_extra_orcamentaria: [unidade_orcamentaria: :tipo_de_unidade_administrativa]).where('contabilidade_estorno_de_despesas_extra_orcamentarias.arquivo_id is null AND 
			contabilidade_estorno_de_despesas_extra_orcamentarias.data_do_estorno >=? AND contabilidade_estorno_de_despesas_extra_orcamentarias.data_do_estorno < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', data, data + 1.months, poder_associado).distinct.all
	end

	def self.retorna_abertura_de_creditos_adicional (data, poder_associado)
		if poder_associado == 1
			dotacoes_destino = Contabilidade::DotacaoDestino.joins(solicitacao_de_alteracao_orcamentaria: :decreto).where("contabilidade_dotacoes_destino.arquivo_id is null").where('contabilidade_solicitacao_de_alteracao_orcamentarias.status = ? AND contabilidade_solicitacao_de_alteracao_orcamentarias.origem_do_recurso in (0, 2, 3, 5)', 4).where('contabilidade_decretos.data_da_legislacao >=?', data).where('contabilidade_decretos.data_da_legislacao < ?', data + 1.months).order(:solicitacao_de_alteracao_orcamentaria_id).all.uniq
		else
			dotacoes_destino = []
		end
		
		return dotacoes_destino
	end

	def self.retorna_fonte_abertura_de_creditos_por_anulacao_de_dotacao (data, poder_associado)	
		if poder_associado == 1
			dotacoes_origem =  Contabilidade::DotacaoOrigem.joins(solicitacao_de_alteracao_orcamentaria: :decreto).where("contabilidade_dotacoes_origem.arquivo_id is null").where('contabilidade_solicitacao_de_alteracao_orcamentarias.status = ? AND contabilidade_solicitacao_de_alteracao_orcamentarias.origem_do_recurso = ?', 4, 0).where('contabilidade_decretos.data_da_legislacao >=?', data).where('contabilidade_decretos.data_da_legislacao < ?', data + 1.months).order(:solicitacao_de_alteracao_orcamentaria_id).all.uniq
		else
			dotacoes_origem = []
		end

		return dotacoes_origem
	end

	def self.retorna_remanejamentos_transposicoes_e_transferencias (data, poder_associado)
		if poder_associado == 1 
			dotacoes_origem = Contabilidade::DotacaoOrigem.joins(solicitacao_de_alteracao_orcamentaria: :decreto).where("contabilidade_dotacoes_origem.arquivo_id_rtt is null").where('contabilidade_solicitacao_de_alteracao_orcamentarias.status = ?', 4).where('contabilidade_decretos.data_da_legislacao >=? AND contabilidade_decretos.data_da_legislacao < ? AND contabilidade_decretos.classificacao in (?)', data, data + 1.months, ["0", "1", "2"]).order(:solicitacao_de_alteracao_orcamentaria_id).all.uniq
		else
			dotacoes_origem = []
		end
		
		return dotacoes_origem
	end

	def self.retorna_destinacao_remanejamentos_transposicoes_e_transferencias (data, poder_associado)
		if poder_associado == 1 
			dotacoes_destino = Contabilidade::DotacaoDestino.joins(solicitacao_de_alteracao_orcamentaria: :decreto).where("contabilidade_dotacoes_destino.arquivo_id_rtt is null").where('contabilidade_solicitacao_de_alteracao_orcamentarias.status = ?', 4).where('contabilidade_decretos.data_da_legislacao >=? AND contabilidade_decretos.data_da_legislacao < ? AND contabilidade_decretos.classificacao in (?)', data, data + 1.months, ["0", "1", "2"]).order(:solicitacao_de_alteracao_orcamentaria_id).all.uniq
		else
			dotacoes_destino = []
		end
		
		return dotacoes_destino
	end

	def self.retorna_movimentacao_fontes_de_recurso (data, poder_associado)
		if poder_associado == 1 
			solicitacoes = Contabilidade::SolicitacaoDeAlteracaoOrcamentaria.joins(:decreto).where("contabilidade_solicitacao_de_alteracao_orcamentarias.arquivo_id is null").where('contabilidade_solicitacao_de_alteracao_orcamentarias.status = ?', 4).where('contabilidade_decretos.data_da_legislacao >=? AND contabilidade_decretos.data_da_legislacao < ?', data, data + 1.months).all
		else
			solicitacoes = []
		end
		
		solicitacoes_ids = []

		solicitacoes.each do |solicitacao|
			if solicitacao.dotacoes_destino.any? && solicitacao.dotacoes_origem.any?
				fontes_origem = solicitacao.dotacoes_origem.joins(orcamento_da_despesa: :fonte_de_recursos).pluck('base_fontes_de_recursos.id')
				fontes_destino = solicitacao.dotacoes_destino.joins(orcamento_da_despesa: :fonte_de_recursos).pluck('base_fontes_de_recursos.id')

				fontes_origem.each do |fonte_origem_id|
					valor_da_fonte_de_origem = solicitacao.dotacoes_origem.joins(orcamento_da_despesa: :fonte_de_recursos).where('base_fontes_de_recursos.id = ?', fonte_origem_id).sum('loa_orcamentos_da_despesa.valor').to_d
					valor_da_fonte_de_destino = solicitacao.dotacoes_destino.joins(orcamento_da_despesa: :fonte_de_recursos).where('base_fontes_de_recursos.id = ?', fonte_origem_id).sum('loa_orcamentos_da_despesa.valor').to_d

					if valor_da_fonte_de_origem != valor_da_fonte_de_destino
						solicitacoes_ids << solicitacao.id
					end
				end
			end
		end

		solicitacoes_a_irem_pro_SIM = Contabilidade::SolicitacaoDeAlteracaoOrcamentaria.where('id in (?)', solicitacoes_ids).all.uniq
		return solicitacoes_a_irem_pro_SIM
	end

	def self.retorna_transferencias_federais (data, poder_associado)
		Obra::Transferencia.joins(unidade_orcamentaria: :tipo_de_unidade_administrativa).where('obra_transferencias.arquivo_id is null AND 
			obra_transferencias.data >= ? AND obra_transferencias.data < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', data, data + 1.months, poder_associado).distinct.all

	end

	def self.retorna_diarias (data, poder_associado)
		Contabilidade::Diaria.joins(empenho: [liquidacoes: :pagamentos]).joins(unidade_orcamentaria: :tipo_de_unidade_administrativa).where('contabilidade_diarias.arquivo_id is null AND 
			contabilidade_pagamentos.data >= ? AND contabilidade_pagamentos.data < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', data, data + 1.months, poder_associado).distinct.all
	end

	def self.retorna_obras (data, poder_associado)
		Contabilidade::Obra.joins(orcamentos_da_despesa: [elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]).where('contabilidade_obras.arquivo_id is null AND 
			contabilidade_obras.envia_pro_sim = true AND contabilidade_obras.data_de_envio_pro_sim >= ? AND contabilidade_obras.data_de_envio_pro_sim < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', data, data + 1.months, poder_associado).distinct.all
	end

	def self.retorna_medicoes_das_obras (data, poder_associado)
		Obra::EmpenhoDaMedicaoDaObra.joins(medicao_da_obra: [liquidacoes: [empenho: [[unidade_orcamentaria: :tipo_de_unidade_administrativa]]]]).joins(medicao_da_obra: :obra)
			.where('contabilidade_obras.envia_pro_sim = TRUE AND obra_empenhos_da_medicao_da_obra.arquivo_id IS NULL AND contabilidade_liquidacoes.id IN (?) AND base_tipos_de_unidades_administrativas.poder_associado = ?', retorna_liquidacoes_sem_marcacao(data, poder_associado).pluck(:id), poder_associado).distinct.all
	end

	def self.retorna_status_das_obras (data, poder_associado)
		situacoes = Contabilidade::SituacaoDaObra.where('contabilidade_situacoes_da_obra.data_da_situacao >= ? AND contabilidade_situacoes_da_obra.data_da_situacao < ? ', data, data + 1.months).select('distinct on(contabilidade_situacoes_da_obra.obra_id) *').order('contabilidade_situacoes_da_obra.obra_id, contabilidade_situacoes_da_obra.id DESC')
		situacoes_das_obras = situacoes.joins(obra: [orcamentos_da_despesa: [elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]]).where('contabilidade_obras.envia_pro_sim = true AND base_tipos_de_unidades_administrativas.poder_associado = ? AND ((contabilidade_situacoes_da_obra.arquivo_id is null AND contabilidade_situacoes_da_obra.tipo_de_status_da_obra <> 2) OR contabilidade_situacoes_da_obra.tipo_de_status_da_obra = 2) ', poder_associado )

		return situacoes_das_obras
	end

	def retorna_conselhos_de_rpps(data)
		orcamento.conselhos_de_rpps.joins(:decreto).where('contabilidade_conselhos_de_rpps.arquivo_id IS NULL AND contabilidade_decretos.data_da_legislacao BETWEEN ? AND ?', data_referencia, data_referencia.end_of_month).distinct.all
	end

	def self.retorna_membros_do_conselhos_de_rpps(data)
		Contabilidade::MembroDoConselhoDoRpps.joins(:conselho_de_rpps)
		.where('(contabilidade_membro_do_conselho_do_rpps.arquivo_id is null AND contabilidade_membro_do_conselho_do_rpps.data_de_admissao BETWEEN ? AND ?)
			OR (contabilidade_membro_do_conselho_do_rpps.arquivo_final_id is null AND contabilidade_membro_do_conselho_do_rpps.data_de_saida BETWEEN ? AND ?)', data, data.end_of_month, data, data.end_of_month).distinct.all
	end

	def retorna_comites_de_ivestimento_rpps(data)
		orcamento.comites_de_investimento.where('contabilidade_comites_de_investimento.arquivo_id is null AND contabilidade_comites_de_investimento.data_da_criacao >= ? AND contabilidade_comites_de_investimento.data_da_criacao < ?', data, data + 1.months).distinct.all
	end

	def self.retorna_responsaveis_pela_geracao(poder_associado)
		tipo_sim = ConfiguracaoSim.tipo_sins[poder_associado]
		Configuracao.last.responsaveis_atuais_do_SIM(tipo_sim)
	end

	def self.retorna_membros_do_comite_de_ivestimento_rpps(data)
		Contabilidade::MembroDoComiteDeInvestimento.where('contabilidade_membros_dos_comites_de_investimento.arquivo_id is null AND contabilidade_membros_dos_comites_de_investimento.data_de_admissao >= ? AND contabilidade_membros_dos_comites_de_investimento.data_de_admissao < ?', data, data + 1.months).distinct.all
	end

	def self.retorna_legislacao_do_rpps(data)
		Contabilidade::Decreto.where('contabilidade_decretos.arquivo_id is null AND contabilidade_decretos.tipo_de_decreto = 2 AND contabilidade_decretos.data_da_legislacao >= ? AND contabilidade_decretos.data_da_legislacao < ?', data, data + 1.months).distinct.all
	end

	def retorna_investimentos_do_rpps
		Contabilidade::InvestimentoDoRpps.where('contabilidade_investimentos_do_rpps.mes_de_competencia = ? AND contabilidade_investimentos_do_rpps.ano_de_competencia = ?', self.mes_de_geracao.to_i , orcamento.exercicio).distinct.all
	end

	def retorna_demonstrativos_de_informacoes_previdenciarias
		Contabilidade::DemonstrativoDeInformacaoPrevidenciaria.where('contabilidade_demonstrativos_de_informacoes_previdenciarias.mes_de_competencia = ? AND contabilidade_demonstrativos_de_informacoes_previdenciarias.ano_de_competencia = ?', self.mes_de_geracao.to_i , orcamento.exercicio).distinct.all
	end

	def self.retorna_aportes_e_despesa(data)
		Contabilidade::AporteDespesa.where('contabilidade_aportes_despesas.arquivo_id is null AND contabilidade_aportes_despesas.data_da_documentacao >= ? AND contabilidade_aportes_despesas.data_da_documentacao < ?', data, data + 1.months).distinct.all
	end

	def self.retorna_transferencias_financeiras (data, poder_associado)
		Contabilidade::TransferenciaFinanceira.joins(conta_bancaria_origem: [unidade_orcamentaria: :tipo_de_unidade_administrativa]).where('contabilidade_transferencias_financeiras.arquivo_id is null AND contabilidade_transferencias_financeiras.data >= ? AND contabilidade_transferencias_financeiras.data < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', data, data + 1.months, poder_associado).order("data asc, numero_da_transferencia asc").distinct.all
	end

	## CONSULTAS DA LICITAÇÃO
	def self.retorna_processos (data, poder_associado)
		Licitacao::Projeto.joins(unidades_orcamentarias_por_pedido: [unidade_orcamentaria: :tipo_de_unidade_administrativa]).where(
			'licitacao_projetos.arquivo_id is NULL AND licitacao_projetos.envia_pro_sim is TRUE AND licitacao_projetos.modalidade_do_processo != ? AND licitacao_projetos.status = ? 
			AND licitacao_projetos.data_de_envio_pro_sim >= ? AND licitacao_projetos.data_de_envio_pro_sim < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', 
			Licitacao::Projeto.modalidades_do_processo[:parceria_osc], Licitacao::Projeto.status[:homologado], data, data + 1.months, poder_associado).distinct.all
	end

	def self.retorna_processos_parcerias (data, poder_associado)
		Licitacao::Projeto.joins(unidades_orcamentarias_por_pedido: [unidade_orcamentaria: :tipo_de_unidade_administrativa]).where(
			'licitacao_projetos.arquivo_id is NULL AND licitacao_projetos.envia_pro_sim is TRUE AND licitacao_projetos.modalidade_do_processo = ? AND licitacao_projetos.status = ? 
			AND licitacao_projetos.data_de_envio_pro_sim >= ? AND licitacao_projetos.data_de_envio_pro_sim < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', 
			Licitacao::Projeto.modalidades_do_processo[:parceria_osc], Licitacao::Projeto.status[:homologado], data, data + 1.months, poder_associado).distinct.all
	end

	def self.retorna_publicacoes_de_processos (data, poder_associado)
		Licitacao::Publicacao.joins(projeto: [unidades_orcamentarias_por_pedido: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]).where(
			'licitacao_publicacoes.arquivo_id is NULL AND licitacao_projetos.envia_pro_sim is TRUE AND licitacao_projetos.modalidade_do_processo != ? AND licitacao_projetos.status = ? 
			AND licitacao_projetos.data_de_envio_pro_sim >= ? AND licitacao_projetos.data_de_envio_pro_sim < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', 
			Licitacao::Projeto.modalidades_do_processo[:parceria_osc], Licitacao::Projeto.status[:homologado], data, data + 1.months, poder_associado).distinct.all
	end

	def self.retorna_publicacoes_de_processos_parcerias (data, poder_associado)
		Licitacao::Publicacao.joins(projeto: [unidades_orcamentarias_por_pedido: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]).where(
			'licitacao_publicacoes.arquivo_id is NULL AND licitacao_projetos.envia_pro_sim is TRUE AND licitacao_projetos.modalidade_do_processo = ? AND licitacao_projetos.status = ? 
			AND licitacao_projetos.data_de_envio_pro_sim >= ? AND licitacao_projetos.data_de_envio_pro_sim < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', 
			Licitacao::Projeto.modalidades_do_processo[:parceria_osc], Licitacao::Projeto.status[:homologado], data, data + 1.months, poder_associado).distinct.all
	end

	def self.retorna_comissoes (data, poder_associado)
		contexto = Orcamento.find_by(exercicio: data.year)
		gestores_id = [] 
		
		gestores = Loa::Gestor.joins(unidade_gestora: [unidades_orcamentarias:[orgao: :tipo_de_unidade_administrativa]]).where('loa_gestores.inicio_da_gestao BETWEEN ? AND ? AND base_tipos_de_unidades_administrativas.poder_associado = ? AND loa_orgaos.orcamento_id = ?', data, data.end_of_month, poder_associado, contexto.id).distinct.all
		gestores.group_by{|gestor| gestor.unidade_gestora_id}.each do |unidade, gestores|
			gestores_id << gestores.sort_by(&:inicio_da_gestao).last.id
		end

		Licitacao::Comissao.joins(projetos: [unidades_orcamentarias_por_pedido: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]).joins(unidade_gestora: :gestores)
			.where('licitacao_projetos.envia_pro_sim = TRUE AND licitacao_projetos.modalidade_do_processo <> ? AND base_tipos_de_unidades_administrativas.poder_associado = ? AND licitacao_projetos.data_de_envio_pro_sim BETWEEN ? AND ? AND 
				(licitacao_comissoes.arquivo_id IS NULL OR (loa_gestores.id IN (?) AND (licitacao_comissoes.data_da_extincao is NULL OR licitacao_comissoes.data_da_extincao > ?)))',
					Licitacao::Projeto.modalidades_do_processo[:parceria_osc], poder_associado, data, data.end_of_month, gestores_id, data.end_of_month).distinct.all

	end

	def self.retorna_comissoes_parcerias (data, poder_associado)
		contexto = Orcamento.find_by(exercicio: data.year)
		gestores_id = [] 
		
		gestores = Loa::Gestor.joins(unidade_gestora: [unidades_orcamentarias:[orgao: :tipo_de_unidade_administrativa]]).where('loa_gestores.inicio_da_gestao BETWEEN ? AND ? AND base_tipos_de_unidades_administrativas.poder_associado = ? AND loa_orgaos.orcamento_id = ?', data, data.end_of_month, poder_associado, contexto.id).distinct.all
		gestores.group_by{|gestor| gestor.unidade_gestora_id}.each do |unidade, gestores|
			gestores_id << gestores.sort_by(&:inicio_da_gestao).last.id
		end
		
		Licitacao::Comissao.joins(projetos: [unidades_orcamentarias_por_pedido: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]).joins(unidade_gestora: :gestores)
			.where('licitacao_projetos.envia_pro_sim = TRUE AND licitacao_projetos.modalidade_do_processo = ? AND base_tipos_de_unidades_administrativas.poder_associado = ? AND licitacao_projetos.data_de_envio_pro_sim BETWEEN ? AND ? AND 
				(licitacao_comissoes.arquivo_id IS NULL OR (loa_gestores.id IN (?) AND (licitacao_comissoes.data_da_extincao is NULL OR licitacao_comissoes.data_da_extincao > ?)))',
					Licitacao::Projeto.modalidades_do_processo[:parceria_osc], poder_associado, data, data.end_of_month, gestores_id, data.end_of_month).distinct.all
	end

	def self.retorna_membros_das_comissoes (data, poder_associado)
		Licitacao::MembroDaComissao.joins(comissao: [projetos: [unidades_orcamentarias_por_pedido: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]).where(
			'licitacao_membros_da_comissao.arquivo_id is NULL AND (licitacao_projetos.arquivo_id != 0 OR licitacao_projetos.arquivo_id is NULL) AND licitacao_projetos.modalidade_do_processo != ?
			AND licitacao_projetos.data_de_envio_pro_sim >= ? AND licitacao_projetos.data_de_envio_pro_sim < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', 
			Licitacao::Projeto.modalidades_do_processo[:parceria_osc], data, data + 1.months, poder_associado).distinct.all
	end

	def self.retorna_membros_das_comissoes_parcerias (data, poder_associado)
		Licitacao::MembroDaComissao.joins(comissao: [projetos: [unidades_orcamentarias_por_pedido: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]).where(
			'licitacao_membros_da_comissao.arquivo_id is NULL AND (licitacao_projetos.arquivo_id != 0 OR licitacao_projetos.arquivo_id is NULL) AND licitacao_projetos.modalidade_do_processo = ?
			AND licitacao_projetos.data_de_envio_pro_sim >= ? AND licitacao_projetos.data_de_envio_pro_sim < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', 
			Licitacao::Projeto.modalidades_do_processo[:parceria_osc], data, data + 1.months, poder_associado).distinct.all
	end

	def self.retorna_itens_do_processo(data, poder_associado)
		processo_ids = Licitacao::ConfiguracaoSimDoProjeto.where('arquivo_id IS NULL AND data_de_envio BETWEEN ? AND ?', data, data.end_of_month).pluck(:projeto_id)

		Licitacao::ItemDoLote.itens_dos_lotes_ativos
			.joins(lote: [processo: [unidades_orcamentarias_por_pedido: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]])
			.where(licitacao_projetos: { id: processo_ids, status: Licitacao::Projeto.status[:homologado], envia_pro_sim: true })
			.where(licitacao_itens_do_lote: { arquivo_id: nil })
			.where(base_tipos_de_unidades_administrativas: { poder_associado: poder_associado })
			.where.not(
				licitacao_projetos: {
					modalidade_do_processo: Licitacao::Projeto.modalidades_do_processo.except[:parceria_osc],
					arquivo_id: nil
				},
				licitacao_lotes: {
					ganhador_id: nil
				}
			)
			.distinct
	end

	def self.retorna_dotacoes_dos_processo (data, poder_associado)
		Licitacao::OrcamentoDaDespesaPorProjeto.includes(orcamento_da_despesa: [elemento_de_despesa_por_subacao: [subacao: :unidade_orcamentaria]]).joins(projeto: [unidades_orcamentarias_por_pedido: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]).where(
			'licitacao_orcamentos_da_despesa_por_projetos.arquivo_id is NULL AND licitacao_projetos.envia_pro_sim is TRUE AND licitacao_projetos.modalidade_do_processo != ? AND licitacao_projetos.status = ? 
			AND licitacao_projetos.data_de_envio_pro_sim >= ? AND licitacao_projetos.data_de_envio_pro_sim < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', 
			Licitacao::Projeto.modalidades_do_processo[:parceria_osc], Licitacao::Projeto.status[:homologado], data, data + 1.months, poder_associado).distinct.all
	end

	def self.retorna_dotacoes_dos_processo_parcerias (data, poder_associado)
		Licitacao::OrcamentoDaDespesaPorProjeto.includes(orcamento_da_despesa: [elemento_de_despesa_por_subacao: [subacao: :unidade_orcamentaria]]).joins(projeto: [unidades_orcamentarias_por_pedido: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]).where(
			'licitacao_orcamentos_da_despesa_por_projetos.arquivo_id is NULL AND licitacao_projetos.envia_pro_sim is TRUE AND licitacao_projetos.modalidade_do_processo = ? AND licitacao_projetos.status = ? 
			AND licitacao_projetos.data_de_envio_pro_sim >= ? AND licitacao_projetos.data_de_envio_pro_sim < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?', 
			Licitacao::Projeto.modalidades_do_processo[:parceria_osc], Licitacao::Projeto.status[:homologado], data, data + 1.months, poder_associado).distinct.all
	end

	def self.retorna_contratos (data, poder_associado)
		Licitacao::Contrato.where(envia_pro_sim: true, status: [Licitacao::Contrato.status["fechado"], Licitacao::Contrato.status["rescindido"]]).joins(contratado: [pessoa_do_projeto: [projeto: [ unidades_orcamentarias_por_pedido: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]]).where.not(licitacao_projetos: {modalidade_do_processo: Licitacao::Projeto.modalidades_do_processo[:parceria_osc] }).where("licitacao_contratos.arquivo_id is null").where('licitacao_contratos.data_de_envio_pro_sim >= ?', data).where('licitacao_contratos.data_de_envio_pro_sim < ?', data + 1.months).where('base_tipos_de_unidades_administrativas.poder_associado = ?', poder_associado).distinct.all
	end

	def self.retorna_aditivos (data, poder_associado)
		Licitacao::Aditivo.que_devem_ir_pro_sim.joins(contrato: :projeto).joins(contrato:[unidade_orcamentaria_por_pedido: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]).where("licitacao_aditivos.arquivo_id is null").where('licitacao_aditivos.data_de_envio_pro_sim >= ?', data).where('licitacao_aditivos.data_de_envio_pro_sim < ?', data + 1.months).where('base_tipos_de_unidades_administrativas.poder_associado = ?', poder_associado).where.not("licitacao_projetos.modalidade_do_processo = 3").distinct.all
	end

	def self.retorna_aditivos_de_parceria_osc (data, poder_associado)
		Licitacao::Aditivo.que_devem_ir_pro_sim.aditivos_de_parceria_osc.where('licitacao_aditivos.data_de_envio_pro_sim >= ?', data).where('licitacao_aditivos.data_de_envio_pro_sim < ?', data + 1.months).where('base_tipos_de_unidades_administrativas.poder_associado = ?', poder_associado).distinct.all
	end

	def self.retorna_contratos_parcerias (data, poder_associado)
		Licitacao::Contrato.where(envia_pro_sim: true, status: [Licitacao::Contrato.status["fechado"], Licitacao::Contrato.status["rescindido"]]).joins(contratado: [pessoa_do_projeto: [projeto: [ unidades_orcamentarias_por_pedido: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]]).where(licitacao_projetos: {modalidade_do_processo: Licitacao::Projeto.modalidades_do_processo[:parceria_osc] }).where("licitacao_contratos.arquivo_id is null").where('licitacao_contratos.data_de_envio_pro_sim >= ?', data).where('licitacao_contratos.data_de_envio_pro_sim < ?', data + 1.months).where('base_tipos_de_unidades_administrativas.poder_associado = ?', poder_associado).distinct.all
	end

	def self.retorna_contratados_por_contrato (data, poder_associado)
		Licitacao::Contratado.joins(:contrato).where(licitacao_contratos: {status: [Licitacao::Contrato.status["fechado"], Licitacao::Contrato.status["rescindido"]], envia_pro_sim: true})
			.joins(pessoa_do_projeto: [projeto:[unidades_orcamentarias_por_pedido: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]).where.not(licitacao_projetos: {modalidade_do_processo: Licitacao::Projeto.modalidades_do_processo[:parceria_osc] })
				.where("licitacao_contratados.arquivo_id is null").where('licitacao_contratos.data_de_envio_pro_sim >= ?', data).where('licitacao_contratos.data_de_envio_pro_sim < ?', data + 1.months).where('base_tipos_de_unidades_administrativas.poder_associado = ?', poder_associado).distinct.all
	end

	def self.retorna_contratados_por_aditivo (data, poder_associado)
		Licitacao::Contratado.joins(aditivo: [contrato: [unidade_orcamentaria_por_pedido: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]).que_devem_ir_pro_sim.where(licitacao_aditivos: {envia_pro_sim: true, status: Licitacao::Aditivo.status["confirmado"]})
			.where("licitacao_contratados.arquivo_id is null").where('licitacao_aditivos.data_de_envio_pro_sim >= ?', data).where('licitacao_aditivos.data_de_envio_pro_sim < ?', data + 1.months).where('base_tipos_de_unidades_administrativas.poder_associado = ?', poder_associado).distinct.all
	end

	def self.movimentacoes_de_receita(data_inicial, poder_associado)
		movimentacoes = Contabilidade::MovimentacaoDoPlanoDeContas.joins(:evento_contabil).sem_encerramento.where("contabilidade_eventos_contabeis.modelo = ?", Contabilidade::EventoContabil.modelos[:talao_de_receita])
			.joins(unidade_orcamentaria: :tipo_de_unidade_administrativa).where("contabilidade_movimentacoes_do_plano_de_contas.tipo_de_lancamento = 0 and contabilidade_movimentacoes_do_plano_de_contas.data_de_lancamento >= ? 
				AND contabilidade_movimentacoes_do_plano_de_contas.data_de_lancamento <= ? AND base_tipos_de_unidades_administrativas.poder_associado = ?",
				data_inicial, data_inicial.end_of_month, poder_associado).where("codigo_da_conta like any(array['5________', '6________'])").where(unidade_orcamentaria_id: 446).where(gerador_id: 4230)

		return movimentacoes
	end

	def self.todas_as_movimentacoes_de_receita(data_inicial, poder_associado)
		movimentacoes = Contabilidade::MovimentacaoDoPlanoDeContas.joins(:evento_contabil).sem_encerramento.where("contabilidade_eventos_contabeis.modelo = ?", Contabilidade::EventoContabil.modelos[:talao_de_receita])
			.joins(unidade_orcamentaria: :tipo_de_unidade_administrativa).where("contabilidade_movimentacoes_do_plano_de_contas.tipo_de_lancamento = 0 and contabilidade_movimentacoes_do_plano_de_contas.data_de_lancamento <= ? AND base_tipos_de_unidades_administrativas.poder_associado = ?",
				data_inicial.end_of_month, poder_associado).where("codigo_da_conta like any(array['5________', '6________'])").where(unidade_orcamentaria_id: 446).where(gerador_id: 4230)

		return movimentacoes
	end

	def self.movimentacoes_de_despesa(data_inicial, poder_associado)
		Contabilidade::MovimentacaoDoPlanoDeContas.joins(:evento_contabil).sem_encerramento.where("contabilidade_eventos_contabeis.modelo = ?", Contabilidade::EventoContabil.modelos[:pagamento])
			.joins(unidade_orcamentaria: :tipo_de_unidade_administrativa).where("contabilidade_movimentacoes_do_plano_de_contas.data_de_lancamento >= ?
				AND contabilidade_movimentacoes_do_plano_de_contas.data_de_lancamento <= ? AND base_tipos_de_unidades_administrativas.poder_associado = ?",
				data_inicial, data_inicial.end_of_month, poder_associado)
	end

	def self.todas_as_movimentacoes_de_despesa(data_inicial, poder_associado)
		Contabilidade::MovimentacaoDoPlanoDeContas.joins(:evento_contabil).sem_encerramento.where("contabilidade_eventos_contabeis.modelo = ?", Contabilidade::EventoContabil.modelos[:pagamento])
			.joins(unidade_orcamentaria: :tipo_de_unidade_administrativa).where("contabilidade_movimentacoes_do_plano_de_contas.data_de_lancamento <= ? AND base_tipos_de_unidades_administrativas.poder_associado = ?",
				data_inicial.end_of_month, poder_associado)
	end

	def self.retorna_bens_patrimoniais(data_referencia, poder_associado)
		Patrimonio::BemPatrimonial
			.where("data_do_tombamento BETWEEN ? AND ?", data_referencia.to_date, data_referencia.end_of_month.to_date)
			.joins(unidade_gestora: [unidades_orcamentarias: :tipo_de_unidade_administrativa])
			.where("base_tipos_de_unidades_administrativas.poder_associado = ?", poder_associado)
			.distinct
	end

	def self.retorna_bens_por_unidade(data_referencia, poder_associado)
		Patrimonio::BemPatrimonial.joins(recebimento_de_bem: [unidade_orcamentaria: :tipo_de_unidade_administrativa])
			.joins('INNER JOIN patrimonio_localizacoes_dos_bens ON patrimonio_localizacoes_dos_bens.id = patrimonio_bens_patrimoniais.localizacao_atual_id')
				.where('patrimonio_recebimentos_de_bens.status = 3 AND patrimonio_localizacoes_dos_bens.data_de_inicio_na_localizacao BETWEEN ? AND ? AND base_tipos_de_unidades_administrativas.poder_associado = ? AND patrimonio_bens_patrimoniais.unidade_gestora_id <> 517', data_referencia, data_referencia.end_of_month, poder_associado).distinct.all
	end

	def self.retorna_ajuste_reavaliacao_patrimonial(data_referencia, poder_associado)
		bens_patrimoniais = Patrimonio::BemPatrimonial.find_by_sql("SELECT dados.valor_residual, (dados.valor_de_aquisicao - dados.valor_residual) as restante, 
			dados.valor_de_aquisicao, subquery.valor_total as VBA, bens.id FROM patrimonio_bens_patrimoniais as bens
			INNER JOIN patrimonio_dados_extras_dos_bens as dados on bens.dados_extras_do_bem_id = dados.id
			INNER JOIN ( SELECT bem_patrimonial_id as bem, sum(valor_da_operacao) AS valor_total FROM patrimonio_movimentacoes_financeiras_dos_bens GROUP BY bem_patrimonial_id) AS subquery ON bens.id = subquery.bem
			WHERE dados.valor_residual > subquery.valor_total AND subquery.valor_total > 0")

		Patrimonio::MovimentacaoFinanceiraDoBem.joins(bem_patrimonial: [unidade_gestora: [unidades_orcamentarias: :tipo_de_unidade_administrativa]])
			.where('base_tipos_de_unidades_administrativas.poder_associado = ? AND patrimonio_movimentacoes_financeiras_dos_bens.bem_patrimonial_id not in (?) 
				AND patrimonio_movimentacoes_financeiras_dos_bens.origem_type IS NOT NULL 
				AND patrimonio_movimentacoes_financeiras_dos_bens.data_da_movimentacao BETWEEN ? AND ? AND patrimonio_bens_patrimoniais.unidade_gestora_id <> 517', 
				poder_associado, bens_patrimoniais.pluck(:id), data_referencia, data_referencia.end_of_month).distinct.all.order(:bem_patrimonial_id)

	end

	def valida_decretos
		decretos = Contabilidade::Decreto.joins(solicitacao_de_alteracao_orcamentarias: :dotacoes_destino).where("contabilidade_dotacoes_destino.id IN (?)", Tcm::Lote.retorna_abertura_de_creditos_adicional(data_referencia, poder_associado).pluck(:id)).distinct.all
		
		decretos.where("contabilidade_decretos.status = 0").each do |decreto|
			raise "É necessário fechar o Decreto(id: #{decreto.id} - número: #{decreto.numero} - tipo de cŕedito: #{decreto.tipo_de_credito_i18n} - classificação: #{decreto.classificacao_i18n})"
		end
	end

	def valida_dotacoes
		orcamento.orcamentos_da_despesa.all.each do |orcamento_da_despesa|
			orcamento_da_despesa.valida_se_possui_dotacao_negativa_no_mes(data_referencia, true)
		end
	end
	
	def sim_deve_ser_unico
		errors.add(:mes_de_referencia, 'Já foi gerado o SIM do mês') if lotes_ja_foram_gerados?
	end

	def lotes_ja_foram_gerados?
		if todos?
			orcamento.lotes_do_tcm.where(mes_de_referencia: mes_de_referencia, tipo_de_poder: tipo_de_poder).where.not(situacao: 'cancelado').any?
		else
			orcamento.lotes_do_tcm.where(tipo: [tipo, 'todos'], mes_de_referencia: mes_de_referencia, tipo_de_poder: tipo_de_poder).where.not(situacao: 'cancelado').any?
		end
	end

	def horario_de_geracao_permitido
		unless Configuracao.last.bloqueio_geral_before_type_cast.to_i == 1
			if gerando_lote_individual.nil? && new_record? && (1..5).include?(Time.now.wday) && Time.now.hour.between?(8, 17)
				errors.add(:base, "Não é permitido gerar lotes do SIM das 8:00 as 17:00 horas")
			end
		end
	end

	def valida_se_possui_balancete_pcasp_gerado
		errors.add(:base, "Balancete de verificações do mês não foi gerado!") if balancete_pcasp_gerado?(data_referencia) == false && self.aprovacao_loa? == false
	end
	
	def criticas_bloqueadoras
		ActiveRecord::Base.transaction do
			begin
				valida_decretos if self.tipo && (self.contabilidade? || self.todos?) && orcamento.present?
				valida_dotacoes if self.tipo && (self.contabilidade? || self.orcamento?)
			rescue => e
				errors.add(:base, e.message)
				raise
				raise ActiveRecord::Rollback, "#{e.message}"
			end
		end
	end
end
