class Tcm::ErrosDoLote < ApplicationRecord
	has_paper_trail
	include TradutorConcern
	include SimConcern
	#concerns na qual possuem o metodo to_sim
	include Tcm::TalaoDeReceitaConcern
	include Tcm::TalaoDeReceitaExtraConcern
	include Tcm::AnulacaoDoTalaoDeReceitaConcern
	include Tcm::AnulacaoDoTalaoDeReceitaExtraConcern
	include Tcm::EmpenhoConcern
	include Tcm::AnulacaoDoEmpenhoConcern
	include Tcm::LiquidacaoConcern
	include Tcm::NotaFiscalConcern
	include Tcm::ItemDaNotaFiscalConcern
	include Tcm::PagamentoConcern
	include Tcm::PagamentoDeFolhaConcern
	include Tcm::ChequeDePagamentoConcern

	include Tcm::LicitanteConcern
	include Tcm::LicitanteDeParceriaConcern

	belongs_to :orcamento, required: true
	has_many :criticas_do_modelo_do_sim, class_name: "Tcm::CriticaDoModeloDoSim", dependent: :destroy

	attr_default :situacao, 1
	attr_default :consulta_avancada, false

	validates_presence_of :orcamento_id, :tipo
	validates_presence_of :mes_de_referencia, :tipo_de_poder, on: :create

	# LICITAÇÃO
	after_create :gera_todos_os_erros_do_lote_da_licitacao
	after_create :gera_todos_os_erros_do_lote_da_contabilidade
	after_create :gera_todos_os_erros_do_lote_do_orcamento
	after_create :gera_todos_os_erros_do_lote_do_patrimonio
	after_create :define_situacao

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

	enum situacao: {
		"sem_erros": 1,
		"com_erros": 2
	}
	
	# o enum foi feito assim para ficar no mesmo padrão do tipo do poder do Lote
	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 exercicio_e_nome_do_mes
		exercicio_e_mes = orcamento.exercicio.to_s
		exercicio_e_mes << " / " << Date::MONTHNAMES[Tcm::ErrosDoLote.mes_de_referencias[self.mes_de_referencia]] unless self.mes_de_referencia.blank?
	end

	def exercicio_e_mes_de_referencia
		exercicio_e_mes = orcamento.exercicio.to_s

		mes = self.read_attribute_before_type_cast(:mes_de_referencia).to_s
		if mes.strip.length > 2
			mes = mes.strip[0..1]
		else
			mes = mes.strip.rjust(2, '0')
		end

		exercicio_e_mes << mes unless self.mes_de_referencia.nil?
	end

	# CONTABILIDADE
	def gera_todos_os_erros_do_lote_da_contabilidade
		if (self.contabilidade? || self.todos?) && orcamento
			ActiveRecord::Base.transaction do
				begin
					gera_erros_talao_de_receita
					gera_erros_talao_de_receita_extra_orcamentarias
					gera_erros_anulacao_do_talao_de_receita
					gera_erros_anulacao_do_talao_de_receita_extra
					gera_erros_dos_empenhos
					gera_erros_anulacoes_do_empenho
					gera_erros_liquidacoes
					gera_erros_das_notas_fiscais
					gera_erros_itens_das_notas
					gera_erros_pagamentos
					gera_erros_pagamentos_de_folha
					gera_erros_cheque_de_nota_de_pagamento
					gera_erros_deducoes_de_notas_de_pagamento
					gera_erros_estornos_de_liquidacao
					gera_erros_estornos_de_pagamento
					gera_erros_despesas_extra_orcamentarias
					gera_erros_estornos_despesas_extra_orcamentarias
					gera_erros_abertura_de_credito_adicional
					gera_erros_fontes_de_abertura_de_credito_adicional
					gera_erros_remanejamentos_transposicoes_e_transferencias
					gera_erros_destinacao_remanejamentos_transposicoes_e_transferencias
					gera_erros_movimentacao_fontes_de_recurso
					gera_erros_transferencias_federais
					gera_erros_diarias
					gera_erros_obras 
					gera_erros_medicoes_das_obras
					gera_erros_status_da_obra
					gera_erros_transferencias_financeiras
					gera_erros_dos_responsaveis_pela_geracao_e_envio_de_contas_mensais

					if self.consulta_avancada?
						gera_erros_balancetes_de_despesas_orcamentarias
						gera_erros_balancetes_de_receitas_orcamentarias
						gera_erros_balancetes_de_receitas_extras_orcamentarias
						gera_erros_balancetes_de_despesas_extras_orcamentarias
						gera_erros_balancetes_de_receitas_orcamentarias_pcasp
						gera_erros_balancetes_de_despesas_orcamentarias_pcasp
						gera_erros_balancetes_das_contas_bancarias_pcasp
						gera_erros_balancetes_das_contas_pcasp
					end
					
					
					if self.executivo?
						gera_erros_parcelamentos_de_rpps
						gera_erros_acompanhamentos_de_parcelamento_de_rpps
						gera_erros_conselhos_de_rpps
						gera_erros_demonstrativos_de_informacoes_previdenciarias
						gera_erros_membros_do_conselhos_de_rpps
						gera_erros_investimentos_do_rpps
						gera_erros_comites_de_ivestimento_rpps
						gera_erros_aportes_e_despesa
						gera_erros_membros_do_comite_de_ivestimento_rpps
						gera_erros_decretos_de_rpps
					end

					if self.mes_de_geracao == "01"
						gera_erros_alocacao_de_recursos
					end

					gera_erros_gestores
					gera_erros_contas_bancarias_municipais
					gera_erros_contas_extra_orcamentarias
					gera_erros_unidade_gestora
					gera_erros_ordenador_de_despesa
					gera_erros_sub_elementos
					# gera_erros_eventos
				rescue => e
					errors.add(:base, e.message)
					raise
					raise ActiveRecord::Rollback, "Alguns erros foram encontrados."
				end
			end
		end
	end

	# LICITAÇÃO
	def gera_todos_os_erros_do_lote_da_licitacao
		if (self.licitacao? || self.todos?) && orcamento
			ActiveRecord::Base.transaction do
				begin
					gera_erros_processos
					gera_erros_comissoes
					gera_erros_membros_das_comissoes
					gera_erros_licitantes
					gera_erros_itens
					gera_erros_contratos
					gera_erros_aditivos
					gera_erros_contratados
					gera_erros_publicacoes_de_processos
					gera_erros_dotacoes_dos_processos

					#Parcerias OSC
					gera_erros_processos_parcerias
					gera_erros_comissoes_parcerias
					gera_erros_membros_das_comissoes_parcerias
					gera_erros_licitantes_parcerias
					gera_erros_contratos_parcerias
					gera_erros_publicacoes_de_processos_parcerias
					gera_erros_dotacoes_dos_processos_parcerias
				rescue => e
					errors.add(:base, e.message)
					raise
					raise ActiveRecord::Rollback, "Alguns erros foram encontrados."
				end
			end
		end
	end

	# ORÇAMENTO
	def gera_todos_os_erros_do_lote_do_orcamento
		if (self.orcamento? || self.todos?) && orcamento
			ActiveRecord::Base.transaction do
				begin
					if self.mes_de_geracao == "01"
						gera_erros_orcamentos
						gera_erros_de_programas_de_governo
					end
					gera_erros_de_orcamento_das_despesas_por_projetos
					gera_erros_de_orcamentos_das_receitas
					gera_erros_orcamentos_da_despesa_e_elementos_da_despesa
					gera_erros_de_orgaos
					gerar_erros_de_unidades_orcamentarias

				rescue => e
					errors.add(:base, e.message)
					raise
					raise ActiveRecord::Rollback, "Alguns erros foram encontrados."
				end
			end
		end
	end

	def gera_todos_os_erros_do_lote_do_patrimonio
		if (self.patrimonio? || self.todos?) && orcamento
			ActiveRecord::Base.transaction do
				begin
					gerar_erros_bens_patrimoniais
					gerar_erros_bens_por_unidade
					gerar_erros_bens_por_empenho
					gerar_erros_ajuste_reavaliacao_patrimonial                     
					gerar_erros_agentes_do_patrimonio
				rescue => e
					errors.add(:base, e.message)
					raise
					raise ActiveRecord::Rollback, "Alguns erros foram encontrados."
				end
			end
		end
	end

	def gerar_erros_bens_patrimoniais
		Tcm::Lote.retorna_bens_patrimoniais(data_referencia, poder_associado).order(:data_do_tombamento).each do |bem|
			begin
				bem.to_sim(data_referencia)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: bem, erro: e.message)
			end
		end
	end

	def gerar_erros_bens_por_unidade
		Tcm::Lote.retorna_bens_por_unidade(data_referencia, poder_associado).each do |bem|
			begin
				bem.to_sim(data_referencia)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: bem, erro: e.message)
			end
		end
	end

	def gerar_erros_bens_por_empenho
		Tcm::Lote.retorna_bens_patrimoniais(data_referencia, poder_associado).order(:data_do_tombamento).each do |bem|
			begin
				bem.to_sim_bens_por_empenho(data_referencia)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: bem, erro: e.message)
			end
		end
	end

	def gerar_erros_ajuste_reavaliacao_patrimonial
		Tcm::Lote.retorna_ajuste_reavaliacao_patrimonial(data_referencia, poder_associado).order(:data_da_movimentacao).each do |movimentacao|
			begin
				movimentacao.to_sim_ajuste_reavaliacao_patrimonial(data_referencia)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: movimentacao, erro: e.message)
			end

			begin
				movimentacao.to_sim_contas_redutoras_dos_bens(data_referencia)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: movimentacao, erro: e.message)
			end
		end
	end

	def gerar_erros_agentes_do_patrimonio
		agentes_ids = []

		agentes_ids.concat(Tcm::Lote.retorna_bens_patrimoniais(data_referencia, poder_associado).map { |bem| bem.unidade_gestora.gestor_no_periodo(data_referencia.end_of_month)&.id})
		agentes_ids.concat(Tcm::Lote.retorna_bens_por_unidade(data_referencia, poder_associado).map { |bem| bem.unidade_gestora.gestor_no_periodo(data_referencia.end_of_month)&.id })
		agentes_ids.concat(Tcm::Lote.retorna_ajuste_reavaliacao_patrimonial(data_referencia, poder_associado).map { |movimentacao| movimentacao.unidade_orcamentaria(movimentacao.bem_patrimonial.unidade_gestora_id, movimentacao.data_da_movimentacao.year)&.unidade_gestora.gestor_no_periodo(data_referencia.end_of_month)&.id})

		agentes_ids = agentes_ids.flatten.uniq

		agentes = Loa::Gestor.where(' id IN (?) AND (ingresso_sistema_publico_municipal IS NULL OR tipo_relacao_servico_publico IS NULL OR numero_da_portaria IS NULL OR numero_da_portaria = ? OR numero_da_portaria = ?)', agentes_ids, "", "-" )

		agentes.each do |agente|
			info_pendentes = []

			info_pendentes << "Forma de ingresso no sistema municipal" if agente.ingresso_sistema_publico_municipal.nil?
			info_pendentes << "Tipo de relação com o serviço público" if agente.tipo_relacao_servico_publico.nil?
			info_pendentes << "Número de posse" if agente.numero_da_portaria.nil? || agente.numero_da_portaria == "" || agente.numero_da_portaria == "-"

			criticas_do_modelo_do_sim.create(modulo: agente, erro: "É necessário cadastrar #{info_pendentes.join(', ')} para o gestor (id: #{agente.id}, nome: #{agente.nome}, cpf: #{agente.cpf})")
		end
	end

	def gera_erros_transferencias_federais
		Tcm::Lote.retorna_transferencias_federais(data_referencia, poder_associado).each do |transferencia|
			begin
				transferencia.valida_natureza_da_receita
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: transferencia, erro: e.message)
			end

			begin
				transferencia.to_sim(exercicio_e_mes_de_geracao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: transferencia, erro: e.message)
			end
		end
	end

	def gera_erros_dos_empenhos
		empenhos = self.retorna_empenhos(data_referencia, poder_associado)
		empenhos.each do |empenho|
			if empenho.valida_obrigatoriedade_sub_conta_e_movimentacao_pcasp.present?
				erro = "O elemento de gasto (#{empenho.try(:elemento_de_despesa).try(:codigo)}), que está relacionado ao empenho (id: #{empenho.id} - número: #{empenho.try(:numero_do_empenho)} - valor: #{empenho.definir_valor_do_empenho.real_contabil} - UG: #{empenho.unidade_orcamentaria.try(:unidade_gestora).try(:nome)}),
					exige reconhecimento do passivo antes da liquidação da despesa pelo regime de competência. O passivo deve ser reconhecido em movimentação de subconta nos lançamentos manuais."
				criticas_do_modelo_do_sim.create(modulo: empenho, erro: erro)
			end
		end

		empenhos.where.not(contrato_id: nil).group_by{|emp| [emp.contrato, emp.aditivo]}.each do |argumentos, empenho|
			contrato = argumentos[0]
			aditivo = argumentos[1]

			if aditivo.present? && (!aditivo.arquivo_id.present? && (aditivo.data_de_envio_pro_sim.nil? || !aditivo.data_de_envio_pro_sim.between?(data_referencia, data_referencia.end_of_month)))
				erro = "O Aditivo(id:#{aditivo.id}; n°:#{aditivo.numero} do contrato n°:#{aditivo.contrato.numero}) vinculado ao(s) Empenho(s)(id:#{empenhos.pluck(:id).join(', ')}; número: #{empenhos.pluck(:numero_do_empenho).join(', ')}) Não foi enviado ao SIM e não está marcado pra ser enviado na mesma remessa dos empenhos"
			elsif !aditivo.present? && (!contrato.arquivo_id.present? && (contrato.data_de_envio_pro_sim.nil? || !contrato.data_de_envio_pro_sim.between?(data_referencia, data_referencia.end_of_month)))
				erro = "O Contrato(id:#{contrato.id}; n°:#{contrato.numero}) vinculado ao(s) Empenho(s)(id:#{empenhos.pluck(:id).join(', ')}; número:#{empenhos.pluck(:numero_do_empenho).join(', ')}) Não foi enviado ao SIM e não está marcado pra ser enviado na mesma remessa dos empenhos"
			end
			criticas_do_modelo_do_sim.create(modulo: empenhos.first, erro: erro) if erro.present?
		end

		empenhos.each do |empenho|
			begin
				empenho.valida_complementacao_da_fonte_de_recurso
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: empenho, erro: e.message)
			end
		end

		self.carrega_dependencias_para_empenhos
		empenhos.each do |empenho|
			begin
				self.empenho_to_sim(empenho)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: empenho, erro: e.message)
			end
		end
	end

	def gera_erros_sub_elementos
		sub_elementos = Contabilidade::SubElementoDeDespesa.joins(elemento_de_despesa: { modalidade_de_aplicacao: { grupo_de_natureza_da_despesa: :categoria_economica }}).joins(:empenhos)
			.joins("LEFT JOIN orcamentos ON orcamentos.id = base_categorias_economicas.modulo_id")
			.where("orcamentos.exercicio = ?", contexto_atual.exercicio)
			.where("contabilidade_sub_elementos_de_despesa.inativo <> TRUE")
			.where("contabilidade_sub_elementos_de_despesa.sub_elemento_origem_tce_id IS NULL")
			.where("base_elementos_de_despesa.inativo <> TRUE")
			.order("contabilidade_sub_elementos_de_despesa.codigo")
			.distinct

		sub_elementos_tce = NaturezaDaDespesa::SubElementoDeDespesa.pluck(:codigo, :descricao)
		invalidos_no_tce = sub_elementos.pluck(:codigo, :descricao) - sub_elementos_tce

		invalidos_no_tce.uniq.each do |codigo, descricao|
			sub_invalidos = sub_elementos.where("contabilidade_sub_elementos_de_despesa.codigo = '#{codigo}' AND contabilidade_sub_elementos_de_despesa.descricao = '#{descricao}'")
			sub_invalidos.each do |sub_invalido|
				criticas_do_modelo_do_sim.create(modulo: sub_invalido, erro: "O subelemento #{sub_invalido.codigo_formatado_e_descricao}, não está na tabela contida na tabela da natureza da despesa fornecida pelo TCE/CE. Deve ser informado o subelemento equivalente da tabela para o SIM. Ir no módulo Planejamento, despesas/subelementos/editar subelemento e informar o equivalente.")
			end
		end
	end

	def gera_erros_contas_extra_orcamentarias
		contas_extra_orcamentarias = retorna_contas_extras(data_referencia,poder_associado)
		contas_extra_orcamentarias.each do |conta_extra_orcamentaria|
			begin
				conta_extra_orcamentaria.valida_unidades_legislativas_e_executivas
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: conta_extra_orcamentaria, erro: e.message)
			end

			begin
				conta_extra_orcamentaria.to_sim(self.exercicio_e_nome_do_mes)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: conta_extra_orcamentaria, erro: e.message)
			end
		end
	end

	def gera_erros_das_notas_fiscais
		carrega_dependencias_para_notas_fiscais
		notas = Tcm::Lote.retorna_notas_fiscais(data_referencia, poder_associado)
		#validação de incrição estadual é feita pra as notas dos tipos mercadoria(2), mercadoria_produtor(4), mercadoria_e_servico(5) 

		notas.where('contabilidade_notas_fiscais.tipo_da_nota IN (2, 4, 5)').group_by{|nota_fiscal| [nota_fiscal.credor]}.each do |credor, notas_fiscais|
			begin
				notas_fiscais.first.valida_inscricao_estadual
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: notas_fiscais.first.credor, erro: e.message)
			end
		end

		#validação de incrição municipal é feita pra as notas dos tipo servico(1) 
		notas.where('contabilidade_notas_fiscais.tipo_da_nota = 1').group_by{|nota_fiscal| [nota_fiscal.credor]}.each do |credor, notas_fiscais|
			begin
				notas_fiscais.first.valida_inscricao_municipal
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: notas_fiscais.first.credor, erro: e.message)
			end
		end

		notas.each do |nota_fiscal|
			begin
				nota_fiscal_to_sim(nota_fiscal)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: nota_fiscal, erro: e.message)
			end
		end
	end

	def gera_erros_dos_responsaveis_pela_geracao_e_envio_de_contas_mensais
		responsavel = Configuracao.last

		begin
			responsavel.valida_gestor_responsavel(poder_associado)
		rescue => e
			criticas_do_modelo_do_sim.create(modulo: responsavel, erro: e.message)
		end

		begin
			responsavel.valida_responsavel_registro_contabil_PF(poder_associado)
		rescue => e
			criticas_do_modelo_do_sim.create(modulo: responsavel, erro: e.message)
		end

		begin
			responsavel.valida_responsavel_registro_contabil_PJ(poder_associado)
		rescue => e
			criticas_do_modelo_do_sim.create(modulo: responsavel, erro: e.message)
		end

		begin
			responsavel.valida_assessor_informatica_PF(poder_associado)
		rescue => e
			criticas_do_modelo_do_sim.create(modulo: responsavel, erro: e.message)
		end

		begin
			responsavel.valida_assessor_informatica_PJ(poder_associado)
		rescue => e
			criticas_do_modelo_do_sim.create(modulo: responsavel, erro: e.message)
		end

	end

	def gera_erros_eventos
		eventos_contabeis =  self.retorna_eventos_contabeis
		eventos_contabeis.each do |evento_contabil|
			begin
				evento_contabil.send(:valida_dotacoes_despesa)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: evento_contabil, erro: e.message)
			end

			begin
				evento_contabil.send(:valida_receitas)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: evento_contabil, erro: e.message)
			end
		end
	end

	def gera_erros_orcamentos_da_despesa_e_elementos_da_despesa
		orcamentos_da_despesa =  self.retorna_orcamentos_da_despesa
		orcamentos_da_despesa.each do |orcamento_da_despesa|
			begin
				orcamento_da_despesa.to_sim_orcamento_da_despesa
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: orcamento_da_despesa, erro: e.message)
			end

			retorna_elemento_destino.each do |elemento_destino|
				begin
					elemento_destino.to_sim_elementos
				rescue => e
					criticas_do_modelo_do_sim.create(modulo: elemento_destino, erro: e.message)
				end
			end
		end

		orcamento.orcamentos_da_despesa.all.each do |orcamento_da_despesa|
			begin
				orcamento_da_despesa.valida_se_possui_dotacao_negativa_no_mes(data_referencia)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: orcamento_da_despesa, erro: e.message)
			end
		end
	end

	def gera_erros_processos
		processos = Tcm::Lote.retorna_processos(data_referencia, poder_associado).distinct
		processos.each do |processo|

			if !processo.responsavel_cotacao_sim.present?
				criticas_do_modelo_do_sim.create(modulo: processo, erro: "É necessário cadastrar o Responsável pela cotação nos dados de envio ao SIM do Processo(id: #{processo.id} - número: #{processo.numero_do_processo})")
			end

			if !processo.responsavel_elaboracao_sim.present?
				criticas_do_modelo_do_sim.create(modulo: processo, erro: "É necessário cadastrar o Responsável pela elaboração do processo nos dados de envio ao SIM do Processo(id: #{processo.id} - número: #{processo.numero_do_processo})")
			end

			begin
				processo.send(:valida_data_de_autuacao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: processo, erro: e.message)
			end

			begin
				processo.send(:valida_responsavel_juridico)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: processo, erro: e.message)
			end

			begin
				processo.to_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: processo, erro: e.message)
			end
		end
	end

	def gera_erros_processos_parcerias
		processos = Tcm::Lote.retorna_processos_parcerias(data_referencia, poder_associado)
		processos.each do |processo|
			begin
				processo.send(:valida_data_de_autuacao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: processo, erro: e.message)
			end

			begin
				processo.to_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: processo, erro: e.message)
			end
		end
	end

	def gera_erros_comissoes
		comissoes = Tcm::Lote.retorna_comissoes(data_referencia, poder_associado)
		comissoes.each do |comissao|
			begin
				comissao.valida_gestor_da_unidade
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: comissao, erro: e.message)
			end

			begin
				comissao.to_sim(data_referencia)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: comissao, erro: e.message)
			end
		end
	end

	def gera_erros_comissoes_parcerias
		comissoes = Tcm::Lote.retorna_comissoes_parcerias(data_referencia, poder_associado)
		comissoes.each do |comissao|
			begin
				comissao.valida_gestor_da_unidade
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: comissao, erro: e.message)
			end

			begin
				comissao.to_sim_parceria
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: comissao, erro: e.message)
			end
		end
	end

	def gera_erros_membros_das_comissoes
		membros_das_comissoes = Tcm::Lote.retorna_membros_das_comissoes(data_referencia, poder_associado)
		membros_das_comissoes.each do |membro_da_comissao|
			begin
				membro_da_comissao.valida_gestor_da_unidade
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: membro_da_comissao, erro: e.message)
			end

			begin
				membro_da_comissao.to_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: membro_da_comissao, erro: e.message)
			end
		end
	end

	def gera_erros_membros_das_comissoes_parcerias
		membros_das_comissoes = Tcm::Lote.retorna_membros_das_comissoes_parcerias(data_referencia, poder_associado)
		membros_das_comissoes.each do |membro_da_comissao|
			begin
				membro_da_comissao.valida_gestor_da_unidade
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: membro_da_comissao, erro: e.message)
			end

			begin
				membro_da_comissao.to_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: membro_da_comissao, erro: e.message)
			end
		end
	end

	def gera_erros_licitantes
		pessoas_do_projeto = retorna_licitantes
		pessoas_do_projeto.each do |pessoa_do_projeto|
			begin
				pessoa_do_projeto.valida_pessoa_juridica
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: pessoa_do_projeto, erro: e.message)
			end
			begin
				pessoa_do_projeto.valida_cep_pessoa
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: pessoa_do_projeto, erro: e.message)
			end

			begin
				licitante_to_sim(pessoa_do_projeto)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: pessoa_do_projeto, erro: e.message)
			end
		end
	end

	def gera_erros_licitantes_parcerias
		pessoas_do_projeto = retorna_licitantes_parcerias
		pessoas_do_projeto.each do |pessoa_do_projeto|
			begin
				pessoa_do_projeto.valida_pessoa_juridica
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: pessoa_do_projeto, erro: e.message)
			end
			begin
				pessoa_do_projeto.valida_email_pessoa
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: pessoa_do_projeto, erro: e.message)
			end

			begin
				licitante_de_parceria_to_sim(pessoa_do_projeto)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: pessoa_do_projeto, erro: e.message)
			end
		end
	end

	def gera_erros_itens
		itens_do_processo = Tcm::Lote.retorna_itens_do_processo(data_referencia, poder_associado)
		itens_do_processo.each do |item_do_processo|
			begin
				item_do_processo.valida_descricao_do_item
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: item_do_processo, erro: e.message)
			end

			begin
				item_do_processo.to_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: item_do_processo, erro: e.message)
			end
		end
	end

	def gera_erros_contratos
		contratos = Tcm::Lote.retorna_contratos(data_referencia, poder_associado)
		contratos.each do |contrato|

			if !contrato.fiscais_do_contrato.where(ativo: true).last&.agente_publico_municipal&.pessoa&.present? && !contrato.projeto.parceria_osc?
				criticas_do_modelo_do_sim.create(modulo: contrato, erro: "É necessário cadastrar um fiscal para o contrato(id: #{contrato.id} - número: #{contrato.numero} da Unidade Orçamentária: #{contrato.unidade_orcamentaria_do_exercicio.try(:nome)})")
			end

			begin
				contrato.valida_unidade_orcamentaria_do_exercicio
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: contrato, erro: e.message)
			end
			begin
				contrato.valida_gestor_da_unidade
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: contrato, erro: e.message)
			end
			begin
				contrato.valida_contrato_de_obra
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: contrato, erro: e.message)
			end

			begin
				contrato.to_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: contrato, erro: e.message)
			end
		end
	end

	def gera_erros_aditivos
		aditivos = Tcm::Lote.retorna_aditivos(data_referencia, poder_associado)
		aditivos.each do |aditivo|

			if !aditivo.contrato.fiscais_do_contrato.where(ativo: true).last&.agente_publico_municipal&.pessoa&.present?
				criticas_do_modelo_do_sim.create(modulo: aditivo, erro: "É necessário cadastrar um fiscal para o contrato(id: #{aditivo.contrato.id} - número: #{aditivo.contrato.numero} da Unidade Orçamentária: #{aditivo.contrato.unidade_orcamentaria_do_exercicio.try(:nome)})")
			end

			begin
				aditivo.contrato.valida_unidade_orcamentaria_do_exercicio
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: aditivo, erro: e.message)
			end
			begin
				aditivo.contrato.valida_gestor_da_unidade
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: aditivo, erro: e.message)
			end
			begin
				aditivo.valida_gestor_da_unidade if aditivo.unidade_orcamentaria.present?
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: aditivo, erro: e.message)
			end
			begin
				aditivo.contrato.valida_contrato_de_obra
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: aditivo, erro: e.message)
			end
			begin
				aditivo.valida_unidade_orcamentaria_do_exercicio_atual if !aditivo.unidade_orcamentaria.present?
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: aditivo, erro: e.message)
			end

			begin
				aditivo.to_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: aditivo, erro: e.message)
			end
		end
	end

	def gera_erros_contratos_parcerias
		contratos = Tcm::Lote.retorna_contratos_parcerias(data_referencia, poder_associado)
		contratos.each do |contrato|
			begin
				contrato.valida_unidade_orcamentaria_do_exercicio
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: contrato, erro: e.message)
			end
			begin
				contrato.valida_gestor_da_unidade
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: contrato, erro: e.message)
			end
			begin
				contrato.projeto.send(:valida_data_de_autuacao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: contrato, erro: e.message)
			end
			begin
				contrato.valida_cpf_e_responsavel_dirigente
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: contrato, erro: e.message)
			end

			begin
				contrato.to_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: contrato, erro: e.message)
			end
		end
	end

	def gera_erros_aditivos_parcerias
		aditivos = Tcm::Lote.retorna_aditivos_de_parceria_osc(data_referencia, poder_associado)
		aditivos.each do |aditivo|
			criticas_do_modelo_do_sim.create(modulo: aditivo, erro: "É necessário cadastrar um fiscal para o contrato(id: #{aditivo.contrato.id} - número: #{aditivo.contrato.numero})")

			begin
				aditivo.contrato.valida_unidade_orcamentaria_do_exercicio
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: aditivo, erro: e.message)
			end
			begin
				aditivo.contrato.valida_contrato_de_obra
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: aditivo, erro: e.message)
			end
			begin
				aditivo.valida_unidade_orcamentaria_do_exercicio_atual if !aditivo.unidade_orcamentaria.present?
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: aditivo, erro: e.message)
			end

			begin
				aditivo.to_sim_parceria_osc
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: aditivo, erro: e.message)
			end
		end
	end

	def gera_erros_contratados
		contratados_por_contrato = Tcm::Lote.retorna_contratados_por_contrato(data_referencia, poder_associado)
		contratados_por_contrato.each do |contratado_por_contrato|
			begin
				contratado_por_contrato.valida_cep_pessoa
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: contratado_por_contrato, erro: e.message)
			end

			begin
				contratado_por_contrato.to_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: contratado_por_contrato, erro: e.message)
			end
		end
		contratados_por_aditivo = Tcm::Lote.retorna_contratados_por_contrato(data_referencia, poder_associado)
		contratados_por_aditivo.each do |contratado_por_aditivo|
			begin
				contratado_por_aditivo.valida_cep_pessoa
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: contratado_por_aditivo, erro: e.message)
			end

			begin
				contratado_por_aditivo.to_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: contratado_por_aditivo, erro: e.message)
			end
		end
	end

	def gera_erros_publicacoes_de_processos
		publicacoes = Tcm::Lote.retorna_publicacoes_de_processos(data_referencia, poder_associado)
		publicacoes.each do |publicacao|
			begin
				publicacao.to_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: publicacao, erro: e.message)
			end
		end
	end

	def gera_erros_dotacoes_dos_processos
		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|
					begin
						dotacao.to_sim(valor_total)
					rescue => e
						criticas_do_modelo_do_sim.create(modulo: dotacao, erro: e.message)
					end
				end
			end
		end
	end

	def gera_erros_publicacoes_de_processos_parcerias
		publicacoes = Tcm::Lote.retorna_publicacoes_de_processos_parcerias(data_referencia, poder_associado)
		publicacoes.each do |publicacao|
			begin
				publicacao.to_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: publicacao, erro: e.message)
			end
		end
	end

	def gera_erros_dotacoes_dos_processos_parcerias
		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|
					begin
						dotacao.to_sim(valor_total)
					rescue => e
						criticas_do_modelo_do_sim.create(modulo: dotacao, erro: e.message)
					end
				end
			end
		end
	end

	def gera_erros_talao_de_receita
		retorna_taloes_de_receita_orcamentario(data_referencia, poder_associado).each do |talao_de_receita|
			begin
				talao_de_receita_to_sim(talao_de_receita)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: talao_de_receita, erro: e.message)
			end
		end
	end

	def gera_erros_talao_de_receita_extra_orcamentarias
		retorna_taloes_de_receita_extraorcamentario(data_referencia, poder_associado).each do |talao_de_receita|
			begin
				self.talao_de_receita_extra_to_sim(talao_de_receita)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: talao_de_receita, erro: e.message)
			end
		end
	end

	def gera_erros_anulacao_do_talao_de_receita
		retorna_anulacoes_dos_taloes_de_receita_orcamentario(data_referencia, poder_associado).each do |anulacao_do_talao|
			begin
				anulacao_do_talao_to_sim(anulacao_do_talao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: anulacao_do_talao, erro: e.message)
			end
		end
	end

	def gera_erros_anulacao_do_talao_de_receita_extra
		retorna_anulacoes_dos_taloes_de_receita_extra_orcamentario(data_referencia, poder_associado).each do |anulacao_do_talao|
			begin
				anulacao_do_talao_de_receita_extra_to_sim(anulacao_do_talao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: anulacao_do_talao, erro: e.message)
			end
		end
	end

	def gera_erros_anulacoes_do_empenho
		anulacoes_do_empenho = retorna_anulacoes_do_empenho(data_referencia, poder_associado).group_by{|anulacao| [anulacao.empenho, anulacao.data_da_anulacao]}
		anulacoes_do_empenho.each do |criterios, anulacoes_do_empenho|
			anulacao_do_empenho = anulacoes_do_empenho.sort_by(&:numero).last
			total_anulado = anulacoes_do_empenho.sum(&:valor)

			begin
				self.anulacao_to_sim(anulacao_do_empenho, total_anulado)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: anulacao_do_empenho, erro: e.message)
			end
		end
	end

	def gera_erros_liquidacoes
		liquidacoes = retorna_liquidacoes(data_referencia, poder_associado)
		liquidacoes.group_by {|liquidacao| [liquidacao.empenho_id, liquidacao.data_da_liquidacao, liquidacao.tipo_da_folha || ''] }.each do |agrupamento, liquidacoes|
			begin
				liquidacao_to_sim(liquidacoes)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: liquidacoes.min_by(&:numero), erro: e.message)
			end
		end
	end

	def gera_erros_itens_das_notas
		retorna_itens_das_notas.each do |item_da_nota|
			begin
				item_da_nota_fiscal_to_sim(item_da_nota)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: item_da_nota, erro: e.message)
			end
		end
	end

	def gera_erros_pagamentos
		carrega_dependencias_para_pagamentos
		pagamentos = retorna_pagamentos(data_referencia, poder_associado).where.not(id: Tcm::Linha.select(:modulo_id).where(modulo_type: 'Contabilidade::Pagamento', arquivo_referencia: "NP#{exercicio_e_mes_de_geracao}.DCD"))
		saldo_apos_pg = 0
		pagamentos.order(:data).group_by{|pagamento| pagamento.empenho.id}.each do |agrupamento|
			total_pg = 0
			agrupamento[1].each do |pagamento|
				total_pg += pagamento.valor.to_f
				saldo_apos_pg = pagamento.empenho.valor_total_do_empenho - total_pg
				begin
					pagamento_to_sim(pagamento) if pagamento.gera_linha_para_arquivo_do_sim.present? == false
				rescue => e
					criticas_do_modelo_do_sim.create(modulo: pagamento, erro: e.message)
				end
			end
		end
	end

	def gera_erros_pagamentos_de_folha
		carrega_dependencias_para_pagamentos_de_folha
		pagamentos = retorna_pagamentos_de_folha(data_referencia, poder_associado).where.not(id: Tcm::Linha.select(:modulo_id).where(modulo_type: 'Contabilidade::Pagamento', arquivo_referencia: "PF#{exercicio_e_mes_de_geracao}.DCD"))
		pagamentos.each do |pagamento|
			begin
				pagamento_de_folha_to_sim(pagamento) if pagamento.gera_linha_para_arquivo_do_sim.present? == false
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: pagamento, erro: e.message)
			end
		end
	end

	def gera_erros_cheque_de_nota_de_pagamento
		carrega_dependencias_para_cheques_de_pagamentos
		pagamentos = retorna_pagamentos_para_cheque(data_referencia, poder_associado)
		pagamentos.each do |pagamento|
			pagamento.contas_bancarias_por_pagamento.where('base_contas_bancarias_por_pagamento.valor_pago > 0').order(:created_at).each_with_index do |conta, index|
				arquivo_referencia = "CP#{exercicio_e_mes_de_geracao + index.to_s}.DCD"
				unless Tcm::Linha.find_by(modulo_type: pagamento.class.name, modulo_id: pagamento.id, arquivo_referencia: arquivo_referencia).present?
					begin
						cheque_de_pagamento_to_sim(pagamento) if pagamento.gera_linha_para_arquivo_do_sim.present? == false
					rescue => e
						criticas_do_modelo_do_sim.create(modulo: pagamento, erro: e.message)
					end
				end
			end
		end
	end

	def gera_erros_deducoes_de_notas_de_pagamento
		Tcm::Lote.retorna_deducoes_de_notas_de_pagamento(data_referencia, poder_associado).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)
			}

			begin
				deducoes.first.to_sim(exercicio_e_mes_de_geracao, args)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: deducoes.first, erro: e.message)
			end
		end
	end

	def gera_erros_estornos_de_liquidacao
		Tcm::Lote.retorna_estornos_de_liquidacao(data_referencia, poder_associado).each do |estorno_de_liquidacao|
			begin
				estorno_de_liquidacao.to_sim(exercicio_e_mes_de_geracao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: estorno_de_liquidacao, erro: e.message)
			end
		end
	end

	def gera_erros_estornos_de_pagamento
		Tcm::Lote.retorna_estornos_de_pagamento(data_referencia, poder_associado).each do |estorno_de_pagamento|
			begin
				estorno_de_pagamento.to_sim(exercicio_e_mes_de_geracao, poder_associado)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: estorno_de_pagamento, erro: e.message)
			end
		end
	end

	def gera_erros_despesas_extra_orcamentarias
		Tcm::Lote.retorna_despesas_extra(data_referencia, poder_associado).each do |despesa_extra|
			begin
				despesa_extra.conta_extra_orcamentaria.valida_codigo_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: despesa_extra, erro: e.message)
			end

			begin
				despesa_extra.to_sim(exercicio_e_mes_de_geracao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: despesa_extra, erro: e.message)
			end
		end
	end

	def gera_erros_estornos_despesas_extra_orcamentarias
		Tcm::Lote.retorna_estorno_de_despesas_extra(data_referencia, poder_associado).each do |estorno_de_despesa_extra|
			begin
				estorno_de_despesa_extra.to_sim(exercicio_e_mes_de_geracao, poder_associado)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: estorno_de_despesa_extra, erro: e.message)
			end
		end
	end

	def gera_erros_abertura_de_credito_adicional
		system('rake db:define_numero_para_dotacao')
		aberturas_de_credito_adicional = Tcm::Lote.retorna_abertura_de_creditos_adicional(data_referencia, poder_associado)
		
		aberturas_de_credito_adicional.each do |abertura_de_credito_adicional|
			begin
				abertura_de_credito_adicional.to_sim(exercicio_e_mes_de_geracao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: abertura_de_credito_adicional, erro: e.message)
			end
		end
		
		decretos = Contabilidade::Decreto.joins(solicitacao_de_alteracao_orcamentarias: :dotacoes_destino).where("contabilidade_dotacoes_destino.id IN (?)", aberturas_de_credito_adicional.pluck(:id)).distinct.all
		
		decretos.where("(contabilidade_decretos.tipo_de_credito <> 1 AND (numero_da_lei_sim IS NULL OR numero_da_lei_sim = '')) OR (contabilidade_decretos.tipo_de_credito = 1 AND(lei_autorizativa IS NULL OR lei_autorizativa = '')) ").each do |decreto|
			nome_do_campo = decreto.credito_especial? == false ? "Número da Lei pro SIM" : "Lei Autorizativa"
			erro = "É necessário cadastrar #{nome_do_campo} ao Decreto(id: #{decreto.id} - número: #{decreto.numero} - tipo de cŕedito: #{decreto.tipo_de_credito_i18n} - classificação: #{decreto.classificacao_i18n})"
			criticas_do_modelo_do_sim.create(modulo: decreto, erro: erro)
		end

		decretos.where("contabilidade_decretos.status = 0").each do |decreto|
			erro = "É 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})"
			criticas_do_modelo_do_sim.create(modulo: decreto, erro: erro)
		end
	end

	def gera_erros_fontes_de_abertura_de_credito_adicional
		Tcm::Lote.retorna_fonte_abertura_de_creditos_por_anulacao_de_dotacao(data_referencia, poder_associado).each do |abertura_de_credito_adicional|
			begin
				abertura_de_credito_adicional.to_sim_fonte_anulacao(exercicio_e_mes_de_geracao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: abertura_de_credito_adicional, erro: e.message)
			end
		end
	end

	def gera_erros_remanejamentos_transposicoes_e_transferencias
		system('rake db:define_numero_para_dotacao[true]')
		Tcm::Lote.retorna_remanejamentos_transposicoes_e_transferencias(data_referencia, poder_associado).each do |abertura_de_credito_adicional|
			begin
				abertura_de_credito_adicional.to_sim_remanejamentos_transposicoes_e_transferencias(exercicio_e_mes_de_geracao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: abertura_de_credito_adicional, erro: e.message)
			end
		end
	end

	def gera_erros_destinacao_remanejamentos_transposicoes_e_transferencias
		Tcm::Lote.retorna_destinacao_remanejamentos_transposicoes_e_transferencias(data_referencia, poder_associado).each do |abertura_de_credito_adicional|
			begin
				abertura_de_credito_adicional.to_sim_remanejamentos_transposicoes_e_transferencias(exercicio_e_mes_de_geracao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: abertura_de_credito_adicional, erro: e.message)
			end
		end
	end

	def gera_erros_movimentacao_fontes_de_recurso
		Tcm::Lote.retorna_movimentacao_fontes_de_recurso(data_referencia, poder_associado).each do |abertura_de_credito_adicional|
			abertura_de_credito_adicional.dotacoes_origem.each do |dotacao_origem|
				abertura_de_credito_adicional.dotacoes_destino.each do |dotacao_destino|
					if dotacao_origem.orcamento_da_despesa.fonte_de_recursos_id != dotacao_destino.orcamento_da_despesa.fonte_de_recursos_id
						begin
							abertura_de_credito_adicional.to_sim(exercicio_e_mes_de_geracao, dotacao_origem, dotacao_destino)
						rescue => e
							criticas_do_modelo_do_sim.create(modulo: abertura_de_credito_adicional, erro: e.message)
						end
					end
				end
			end
		end
	end

	def gera_erros_diarias
		Tcm::Lote.retorna_diarias(data_referencia, poder_associado).each do |diaria|
			begin
				diaria.to_sim(exercicio_e_mes_de_geracao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: diaria, erro: e.message)
			end
		end
	end

	def gera_erros_obras
		Tcm::Lote.retorna_obras(data_referencia, poder_associado).each do |obra|
			begin
				obra.to_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: obra, erro: e.message)
			end				

			criticas_do_modelo_do_sim.create(modulo: obra, erro: "#{obra.engenheiro_responsavel.pessoa_com_informacoes_pendente.to_s.delete("[\/]\"/")}(id: #{obra.engenheiro_responsavel.pessoa.id}, nome:#{obra.engenheiro_responsavel.pessoa.nome})") if obra.engenheiro_responsavel.pessoa_com_informacoes_pendente.present?
		end
		Contabilidade::Obra.where('data_de_envio_pro_sim IS NULL AND orcamento_id = ?', Orcamento.find_by(exercicio: data_referencia.year)).order(:tipo_de_obra, :codigo, :id).each do |obra|
			criticas_do_modelo_do_sim.create(modulo: obra, erro: "É necessário cadastrar a data de envio ao SIM (id: #{obra.id} - código: #{obra.codigo}.#{obra.data_de_inicio.year.to_s.last(2)} - tipo: #{obra.tipo_de_obra_i18n})")
		end
	end

	def gera_erros_medicoes_das_obras
		Tcm::Lote.retorna_medicoes_das_obras(data_referencia, poder_associado).each do |medicao_da_obra|
			begin
				medicao_da_obra.to_sim(exercicio_e_mes_de_geracao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: medicao_da_obra, erro: e.message)
			end
		end
	end

	def gera_erros_status_da_obra
		Tcm::Lote.retorna_status_das_obras(data_referencia, poder_associado).each do |status_da_obra|
			begin
				status_da_obra.to_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: status_da_obra, erro: e.message)
			end

			begin
				status_da_obra.valida_engenheiro_responsavel_cadastrado
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: status_da_obra, erro: e.message)
			end

			begin
				status_da_obra.valida_tombo_de_obra_concluida
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: status_da_obra, erro: e.message)
			end
		end

		obras = Contabilidade::Obra.joins(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 = ?',poder_associado).distinct.all		
		obras.order(:codigo).each do |obra|
			begin
				obra.verifica_cadastro_de_status_mensal(data_referencia)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: obra, erro: e.message)
			end
		end
	end

	def gera_erros_conselhos_de_rpps
		conselhos_de_rpps = retorna_conselhos_de_rpps
		conselhos_de_rpps.each do |conselho_de_rpps|
			begin
				conselho_de_rpps.to_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: conselho_de_rpps, erro: e.message)
			end
		end
	end

	def gera_erros_decretos_de_rpps
		Tcm::Lote.retorna_legislacao_do_rpps(data_referencia).each do |legislacao_do_rpps|
			begin
				legislacao_do_rpps.to_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: legislacao_do_rpps, erro: e.message)
			end
		end
	end

	def gera_erros_membros_do_conselhos_de_rpps
		Tcm::Lote.retorna_membros_do_conselhos_de_rpps(data_referencia).each do |membro_do_conselho_de_rpps|
			begin
				membro_do_conselho_de_rpps.to_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: membro_do_conselho_de_rpps, erro: e.message)
			end
		end
	end

	def gera_erros_parcelamentos_de_rpps
		parcelamentos_de_rpps = retorna_parcelamentos_do_rpps(data_referencia)
		parcelamentos_de_rpps.each do |parcelamento_de_rpps|
			begin
				parcelamento_de_rpps.to_sim(exercicio_e_mes_de_geracao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: parcelamento_de_rpps, erro: e.message)
			end
		end
	end

	def gera_erros_acompanhamentos_de_parcelamento_de_rpps
		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|
			begin
				acompanhamento_de_parcelamento_de_rpps.to_sim(exercicio_e_mes_de_geracao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: acompanhamento_de_parcelamento_de_rpps, erro: e.message)
			end
		end
	end

	def gera_erros_investimentos_do_rpps
		investimentos_do_rpps = retorna_investimentos_do_rpps
		investimentos_do_rpps.each do |investimento_do_rpps|
			begin
				investimento_do_rpps.to_sim(exercicio_e_mes_de_geracao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: investimento_do_rpps, erro: e.message)
			end
		end
	end

	def gera_erros_demonstrativos_de_informacoes_previdenciarias
		demonstrativos_de_informacoes = retorna_demonstrativos_de_informacoes_previdenciarias
		demonstrativos_de_informacoes.each do |demonstrativo_de_informacao|
			begin
				demonstrativo_de_informacao.to_sim(exercicio_e_mes_de_geracao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: demonstrativo_de_informacao, erro: e.message)
			end
		end
	end

	def gera_erros_aportes_e_despesa
		Tcm::Lote.retorna_aportes_e_despesa(data_referencia).each do |aporte_e_despesa|
			begin
				aporte_e_despesa.to_sim(exercicio_e_mes_de_geracao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: aporte_e_despesa, erro: e.message)
			end
		end
	end

	def gera_erros_comites_de_ivestimento_rpps
		comites_de_ivestimento = retorna_comites_de_ivestimento_rpps(data_referencia)
		comites_de_ivestimento.each do |comite_de_ivestimento|
			begin
				comite_de_ivestimento.to_sim(exercicio_e_mes_de_geracao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: comite_de_ivestimento, erro: e.message)
			end
		end
	end

	def gera_erros_membros_do_comite_de_ivestimento_rpps
		Tcm::Lote.retorna_membros_do_comite_de_ivestimento_rpps(data_referencia).each do |membro_do_comite_de_ivestimento|
			begin
				membro_do_comite_de_ivestimento.to_sim(exercicio_e_mes_de_geracao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: membro_do_comite_de_ivestimento, erro: e.message)
			end
		end
	end

	def gera_erros_transferencias_financeiras
		Tcm::Lote.retorna_transferencias_financeiras(data_referencia, poder_associado).each do |transferencia|
			begin
				transferencia.to_sim(exercicio_e_mes_de_geracao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: transferencia, erro: e.message)
			end
		end
	end

	def gera_erros_balancetes_de_despesas_orcamentarias
		balancetes = retorna_balancetes_de_despesas_orcamentarias(data_referencia, poder_associado)
		balancetes.each do |balancete|
			if balancete.verifica_se_balancete_valido(data_referencia, poder_associado)
				begin
					balancete.to_sim_balancetes_de_despesas_orcamentarias(data_referencia, exercicio_e_mes_de_geracao, poder_associado)
				rescue => e
					criticas_do_modelo_do_sim.create(modulo: balancete, erro: e.message)
				end
			end
		end
		Loa::BalanceteDeDespesaOrcamentaria.where(ano_referencia: data_referencia.year, mes_referencia: data_referencia.month, tipo_de_poder: self.tipo_de_poder).delete_all if lote_do_sim_gerado?(data_referencia) == false
	end

	def gera_erros_balancetes_de_receitas_orcamentarias
		Tcm::Lote.retorna_balancetes_de_recitas_orcamentarias(data_referencia, poder_associado).each do |balancete|
			if balancete.valor_arrecadado_periodo(data_referencia) != 0
				begin
					balancete.to_sim_balancetes_de_receitas_orcamentarias(data_referencia)
				rescue => e
					criticas_do_modelo_do_sim.create(modulo: balancete, erro: e.message)
				end
			end
		end
	end

	def gera_erros_balancetes_de_receitas_extras_orcamentarias
		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
				begin
					balancetes.first.to_sim(data_referencia, args)
				rescue => e
					criticas_do_modelo_do_sim.create(modulo: balancete, erro: e.message)
				end
			end
		end
	end

	def gera_erros_balancetes_de_despesas_extras_orcamentarias
		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
				begin
					balancetes.first.to_sim_balancetes_de_despesas_extra_orcamentarias(data_referencia, args)
				rescue => e
					criticas_do_modelo_do_sim.create(modulo: balancete, erro: e.message)
				end
			end
		end
	end

	def gera_erros_balancetes_de_receitas_orcamentarias_pcasp
		movimentacoes = ActiveRecord::Base.connection.execute("
			SELECT ccec.conta_id, cm.codigo_da_conta, cm.unidade_orcamentaria_id, cm.fonte_de_recursos_id, 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 btua.poder_associado = #{poder_associado}" if poder_associado.present? }
			group by ccec.conta_id, cm.codigo_da_conta, cm.unidade_orcamentaria_id, cm.fonte_de_recursos_id, 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"])
			fonte_de_recursos = Base::FonteDeRecursos.find(movimentacao["fonte_de_recursos_id"]) rescue nil
			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 fonte_de_recursos.present?
				outras_condicoes << "contabilidade_movimentacoes_do_plano_de_contas.fonte_de_recursos_id = #{fonte_de_recursos.id}" 
			else
				outras_condicoes << "contabilidade_movimentacoes_do_plano_de_contas.fonte_de_recursos_id is null"
			end

			movimentacoes_do_periodo = conta.movimentacoes_do_plano_de_contas.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 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: fonte_de_recursos,
				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, fonte_de_recursos.try(:id), ic_nr).to_d,
				saldo_debito_total: Contabilidade::BalanceteDeVerificacao.valor_total_debitos(ids_movimentacoes_dos_balancetes),
				saldo_credito_total: Contabilidade::BalanceteDeVerificacao.valor_total_creditos(ids_movimentacoes_dos_balancetes)
			}

			begin
				conta.to_sim_receita(args)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: conta, erro: e.message)
			end
		end
	end

	def gera_erros_balancetes_de_despesas_orcamentarias_pcasp

		movimentacoes = ActiveRecord::Base.connection.execute("
			SELECT ccec.conta_id, cm.codigo_da_conta, cm.unidade_orcamentaria_id, cm.fonte_de_recursos_id, 
			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, 
			cm.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 btua.poder_associado = #{poder_associado}" if poder_associado.present? }
			group by ccec.conta_id, cm.codigo_da_conta, cm.unidade_orcamentaria_id, cm.fonte_de_recursos_id, 
			bf.id, bsf.id, lpg.id, la.id, ls.id, cm.ic_nd, ic_co_at
			order by ccec.conta_id, cm.codigo_da_conta, cm.unidade_orcamentaria_id, cm.fonte_de_recursos_id, 
			bf.id, bsf.id, lpg.id, la.id, ls.id, cm.ic_nd, ic_co_at
		")

		movimentacoes.each do |movimentacao|
			conta = Contabilidade::Conta.find(movimentacao["conta_id"])
			unidade_orcamentaria = Loa::UnidadeOrcamentaria.find(movimentacao["unidade_orcamentaria_id"])
			fonte_de_recursos = Base::FonteDeRecursos.find(movimentacao["fonte_de_recursos_id"]) rescue nil

			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 fonte_de_recursos.present?
				outras_condicoes << "contabilidade_movimentacoes_do_plano_de_contas.fonte_de_recursos_id = #{fonte_de_recursos.id}" 
			else
				outras_condicoes << "contabilidade_movimentacoes_do_plano_de_contas.fonte_de_recursos_id is null"
			end

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

			movimentacoes_do_periodo_anterior = movimentacoes_query
				.where("ic_nd = ? 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 ic_nd = ? 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 == 'Contabilidade::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: fonte_de_recursos,
				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)
			}

			begin
				args[:conta].to_sim_despesa(args)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: conta, erro: e.message)
			end
		end
	end

	def gera_erros_balancetes_das_contas_bancarias_pcasp
		movimentacoes_de_conta_bancaria = Tcm::Lote.movimentacoes_de_conta_bancaria(data_referencia, poder_associado, orcamento)
		todas_as_movimentacoes_de_conta_bancaria = Tcm::Lote.todas_as_movimentacoes_de_conta_bancaria(data_referencia, poder_associado, orcamento)

		todas_as_movimentacoes_de_conta_bancaria.group_by { |movimentacao|
			[
				movimentacao.conta,
				movimentacao.conta_bancaria,
				movimentacao.unidade_orcamentaria
			]
		}.each do |criterios, movimentacoes|
			conta = criterios[0]
			conta_bancaria = criterios[1]
			unidade_orcamentaria = criterios[2]
			ids_movimentacoes_dos_balancetes = movimentacoes.map {|m| m.movimentacoes_das_contas_do_balancete.ids if m.data_de_lancamento >= data_referencia && m.data_de_lancamento <= data_referencia.end_of_month}.flatten.compact rescue nil

			saldo_debito_total = Contabilidade::BalanceteDeVerificacao.valor_total_debitos(ids_movimentacoes_dos_balancetes).to_d
			saldo_credito_total = Contabilidade::BalanceteDeVerificacao.valor_total_creditos(ids_movimentacoes_dos_balancetes).to_d
			saldo_inicial_do_mes = Contabilidade::BalanceteDeVerificacao.saldo_inicial_da_conta_baseado_no_mes(conta, data_referencia.end_of_month, unidade_orcamentaria, poder_associado, nil, nil, conta_bancaria.id).to_d

			args = {
				mes_de_referencia: read_attribute_before_type_cast(:mes_de_referencia),
				conta_bancaria: criterios[1],
				unidade_orcamentaria: criterios[2],
				saldo_debito_total: saldo_debito_total,
				saldo_credito_total: saldo_credito_total,
				saldo_inicial_do_mes: saldo_inicial_do_mes
			}

			if saldo_debito_total != 0 || saldo_credito_total != 0 || saldo_inicial_do_mes != 0

				begin
					conta.valida_conta_bancaria_para_o_sim(conta_bancaria)
				rescue => e
					criticas_do_modelo_do_sim.create(modulo: conta, erro: e.message)
				end

				begin
					conta.to_sim_contas_bancarias(args)
				rescue => e
					criticas_do_modelo_do_sim.create(modulo: conta, erro: e.message)
				end
			end
		end
	end

	def gera_erros_balancetes_das_contas_pcasp
		movimentacoes = Tcm::Lote.movimentacoes_pcasp(data_referencia, poder_associado)
		todas_as_movimentacoes_ate_o_mes = Tcm::Lote.todas_as_movimentacoes_pcasp_ate_o_fim_do_mes(data_referencia, poder_associado)

		todas_as_movimentacoes_ate_o_mes.group_by{ |movimentacao|
			[
				movimentacao.conta,
				movimentacao.unidade_orcamentaria,
				movimentacao.codigo_superavit_financeiro,
				movimentacao.fonte_de_recursos_id
			]
		}.each do |criterios, movimentacoes|
			conta = criterios[0]
			ids_movimentacoes_dos_balancetes = movimentacoes.map {|m| m.movimentacoes_das_contas_do_balancete.ids if m.data_de_lancamento >= data_referencia && m.data_de_lancamento <= data_referencia.end_of_month}.flatten.compact rescue nil
			ids_movimentacoesdos_balancetes_cb =  movimentacoes.select {|m| m.movimentacoes_das_contas_do_balancete if m.conta_bancaria_id.present? && m.data_de_lancamento >= data_referencia && m.data_de_lancamento <= data_referencia.end_of_month}.flatten.compact.pluck(:id) rescue nil

			args = {
				mes_de_referencia: read_attribute_before_type_cast(:mes_de_referencia),
				unidade_orcamentaria: criterios[1],
				codigo_superavit: criterios[2],
				fonte_de_recursos: criterios[3],
				saldo_debito_total: Contabilidade::BalanceteDeVerificacao.valor_total_debitos(ids_movimentacoes_dos_balancetes),
				saldo_credito_total: Contabilidade::BalanceteDeVerificacao.valor_total_creditos(ids_movimentacoes_dos_balancetes),
				saldo_de_debito_contas_bancarias:Contabilidade::BalanceteDeVerificacao.valor_total_debitos_por_mes(ids_movimentacoesdos_balancetes_cb, data_referencia),
				saldo_de_creditos_contas_bancarias: Contabilidade::BalanceteDeVerificacao.valor_total_creditos_por_mes(ids_movimentacoesdos_balancetes_cb, data_referencia),
				saldo_inicial_do_mes: Contabilidade::BalanceteDeVerificacao.saldo_inicial_da_conta_baseado_no_mes(conta, data_referencia.end_of_month, criterios[1], poder_associado, criterios[3]).to_d
			}

			begin
				conta.to_sim_pcasp(args)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: conta, erro: e.message)
			end
		end
	end

	def gera_erros_alocacao_de_recursos
		alocacoes_de_recurso = retorna_alocacoes_de_recurso(poder_associado)
		alocacoes_de_recurso.each do |alocacao_de_recurso|
			begin
				alocacao_de_recurso.to_sim(exercicio_e_mes_de_geracao)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: alocacao_de_recurso, erro: e.message)
			end
		end
	end

	def gera_erros_gestores
		Tcm::Lote.retorna_gestores(data_referencia, poder_associado, contexto_atual).each do |gestor|
			gestor.unidade_gestora.unidades_orcamentarias.joins(:orgao).where(' loa_orgaos.orcamento_id = ?', contexto_atual.id).each do |unidade_orcamentaria|
				begin
					gestor.to_sim(exercicio_e_mes_de_geracao, unidade_orcamentaria.id)
				rescue => e
					criticas_do_modelo_do_sim.create(modulo: gestor, erro: e.message)
				end
			end
		end
	end

	def gera_erros_contas_bancarias_municipais
		contas_bancarias_orc = Base::ContaBancariaPorUnidadeOrcamentaria.joins(unidade_orcamentaria: [:tipo_de_unidade_administrativa, :orgao]).joins(:conta_bancaria).where('base_contas_bancarias.conta_caixa_pcasp is false AND base_tipos_de_unidades_administrativas.poder_associado = ? AND loa_orgaos.orcamento_id = ?', poder_associado, self.orcamento_id)
		contas_bancarias_orc.where("base_contas_bancarias_por_unidade_orcamentaria.data_de_abertura BETWEEN ? AND ?", data_referencia, data_referencia.end_of_month).each do |conta_por_uo|
			begin
				conta_por_uo.conta_bancaria.to_sim(data_referencia, exercicio_e_mes_de_geracao, orcamento, conta_por_uo.unidade_orcamentaria_id)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: conta_por_uo.conta_bancaria, erro: e.message)
			end
		end

		contas_bancarias_orc.where('base_contas_bancarias_por_unidade_orcamentaria.principal IS NOT TRUE').each do |conta_por_uo|
			if conta_por_uo.saldo_atual.to_d > 0
				principal	= contas_bancarias_orc.where('base_contas_bancarias_por_unidade_orcamentaria.principal IS TRUE AND base_contas_bancarias_por_unidade_orcamentaria.conta_bancaria_id = ?', conta_por_uo.conta_bancaria_id).first.unidade_orcamentaria.codigo_e_nome rescue "principal"
				erro = "A conta bancária Nº #{conta_por_uo.conta_bancaria.numero_da_conta} possui saldo financeiro na unidade #{conta_por_uo.unidade_orcamentaria.codigo_e_nome} de #{conta_por_uo.saldo_atual.to_f.real_contabil}. O saldo deve ser transferido para a unidade #{principal}. Ir em TRANSFERÊNCIAS/FINANCEIRAS, transferir saldo da unidade não principal para a unidade principal."
				criticas_do_modelo_do_sim.create(modulo: conta_por_uo.conta_bancaria, erro: erro)
			end
		end
	end

	def gera_erros_unidade_gestora
		unidades_gestoras = retorna_unidades_gestoras(poder_associado)
		unidades_gestoras.each do |unidade_gestora|
			unidade_gestora.unidades_orcamentarias.joins(orgao: :orcamento).where('orcamentos.exercicio = ?', data_referencia.year).each do |unidade_orcamentaria|
				begin
					unidade_gestora.to_sim(exercicio_e_mes_de_geracao, data_referencia, unidade_orcamentaria.id)
				rescue => e
					criticas_do_modelo_do_sim.create(modulo: unidade_gestora, erro: e.message)
				end
			end
		end
	end

	def gera_erros_ordenador_de_despesa
		Tcm::Lote.retorna_ordenadores_de_despesa(data_referencia, poder_associado, contexto_atual).each do |ordenador_de_despesa|
			begin
				ordenador_de_despesa.to_sim(exercicio_e_mes_de_geracao, data_referencia)
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: ordenador_de_despesa, erro: e.message)
			end
		end
	end 

	def gera_erros_orcamentos
		begin
			orcamento.to_sim
		rescue => e
			criticas_do_modelo_do_sim.create(modulo: orcamento, erro: e.message)
		end
	end

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

		orcamentos_das_receitas = Loa::OrcamentoDaReceita.where("unidade_orcamentaria_por_natureza_da_receita_id in (?)", unidades_orcamentarias_por_natureza_da_receita_ids).all
		orcamentos_das_receitas.each do |receita|
			begin
				receita.to_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: receita, erro: e.message)
			end
		end
	end

	def gera_erros_de_orcamento_das_despesas_por_projetos
		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| 
			begin
				subacao.to_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: subacao, erro: e.message)
			end
		end
	end

	def gera_erros_de_programas_de_governo
		programas_de_governo = orcamento.programas_de_governo.where("arquivo_id is null").all
		programas_de_governo.each do |programa_de_governo|
			begin
				programa_de_governo.to_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: programa_de_governo, erro: e.message)
			end
		end
	end

	def gera_erros_de_orgaos
		orgaos = orcamento.orgaos.where("arquivo_id is null").all
		orgaos.each do |orgao|
			begin
				orgao.to_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: orgao, erro: e.message)
			end
		end
	end

	def gerar_erros_de_unidades_orcamentarias
		orgaos_ids = Loa::Orgao.where(orcamento_id: orcamento.id).all.ids
		unidades_orcamentarias = Loa::UnidadeOrcamentaria.where("arquivo_id is null and orgao_id in (?)", orgaos_ids).all
		unidades_orcamentarias.each do |unidade|
			begin
				unidade.to_sim
			rescue => e
				criticas_do_modelo_do_sim.create(modulo: unidade, erro: e.message)
			end
		end
	end

	def retorna_empenhos (data, poder_associado)
		status_a_utilizar = [Contabilidade::Empenho.status[:confirmado], Contabilidade::Empenho.status[:anulado]]

		orcamento.empenhos.joins(orcamento_da_despesa:[elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]).where('contabilidade_empenhos.status in (?) AND contabilidade_empenhos.data_do_empenho >= ? AND contabilidade_empenhos.data_do_empenho < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?',
		status_a_utilizar, data, data + 1.months, poder_associado).distinct.all
	end

	def retorna_anulacoes_do_empenho (data, poder_associado)
		orcamento.anulacoes_do_empenho.do_orcamento.joins(empenho: [orcamento_da_despesa:[elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]]).where('contabilidade_anulacoes_do_empenho.status = ? AND contabilidade_anulacoes_do_empenho.data_da_anulacao >= ? AND contabilidade_anulacoes_do_empenho.data_da_anulacao < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?',
			Contabilidade::AnulacaoDoEmpenho.status[:confirmado], data, data + 1.months, poder_associado).distinct.all
	end

	def retorna_liquidacoes (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.id).distinct.all

		return liquidacoes
	end

	def retorna_taloes_de_receita_orcamentario (data, poder_associado)
		Contabilidade::ComplementoPorFonteDoTalaoDeReceita.joins(talao_de_receita: [unidade_orcamentaria: :tipo_de_unidade_administrativa]).where('contabilidade_taloes_de_receita.origem_do_talao = ? AND contabilidade_taloes_de_receita.data_do_talao >= ? AND contabilidade_taloes_de_receita.data_do_talao < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?',
			Contabilidade::TalaoDeReceita.origem_dos_taloes[:orcamentario], data, data + 1.months, poder_associado).distinct.all
	end

	def retorna_taloes_de_receita_extraorcamentario (data, poder_associado)
		Contabilidade::TalaoDeReceita.joins(unidade_orcamentaria: :tipo_de_unidade_administrativa).where('contabilidade_taloes_de_receita.origem_do_talao = ? AND contabilidade_taloes_de_receita.data_do_talao >= ? AND contabilidade_taloes_de_receita.data_do_talao < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?',
			Contabilidade::TalaoDeReceita.origem_dos_taloes[:extra_orcamentario], data, data + 1.months, poder_associado).distinct.all
	end

	def retorna_anulacoes_dos_taloes_de_receita_orcamentario (data, poder_associado)
		Contabilidade::ComplementoPorFonteDaAnulacaoDoTalao.joins(anulacao_do_talao_de_receita: [talao_de_receita: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]).where('contabilidade_taloes_de_receita.origem_do_talao = ? AND contabilidade_anulacoes_dos_taloes_de_receita.data_da_anulacao >= ? AND contabilidade_anulacoes_dos_taloes_de_receita.data_da_anulacao < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?',
			Contabilidade::TalaoDeReceita.origem_dos_taloes[:orcamentario], data, data + 1.months, poder_associado).distinct.all
	end

	def retorna_anulacoes_dos_taloes_de_receita_extra_orcamentario (data, poder_associado)
		Contabilidade::AnulacaoDoTalaoDeReceita.joins(talao_de_receita: [unidade_orcamentaria: :tipo_de_unidade_administrativa]).where('contabilidade_taloes_de_receita.origem_do_talao = ? AND contabilidade_anulacoes_dos_taloes_de_receita.data_da_anulacao >= ? AND contabilidade_anulacoes_dos_taloes_de_receita.data_da_anulacao < ? AND base_tipos_de_unidades_administrativas.poder_associado = ?',
			Contabilidade::TalaoDeReceita.origem_dos_taloes[:extra_orcamentario], data, data + 1.months, poder_associado).distinct.all
	end

	def retorna_itens_das_notas
		itens = Contabilidade::ItemDaNotaFiscal.joins(liquidacao: [empenho: [orcamento_da_despesa:[elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]]])
			.where('contabilidade_liquidacoes.data_da_liquidacao is not null AND contabilidade_liquidacoes.nota_fiscal_tipo BETWEEN 1 AND 6 AND contabilidade_liquidacoes.status in (2,5,6,8) AND contabilidade_liquidacoes.data_da_liquidacao >= ? AND contabilidade_liquidacoes.data_da_liquidacao <= ? AND contabilidade_liquidacoes.restos_a_pagar <> true', self.data_referencia, self.data_referencia.end_of_month).distinct.all
			.where('base_tipos_de_unidades_administrativas.poder_associado = ?', self.poder_associado)

		itens_rp = Contabilidade::ItemDaNotaFiscal.joins(liquidacao: [empenho: [orcamento_da_despesa:[elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]]])
			.where('contabilidade_liquidacoes.data_da_liquidacao is not null AND contabilidade_liquidacoes.nota_fiscal_tipo BETWEEN 1 AND 6 AND contabilidade_liquidacoes.status in (2,5,6,8) AND contabilidade_liquidacoes.data_da_liquidacao >= ? AND contabilidade_liquidacoes.data_da_liquidacao <= ? AND contabilidade_liquidacoes.restos_a_pagar = true', self.data_referencia, self.data_referencia.end_of_month).distinct.all
			.where('base_tipos_de_unidades_administrativas.poder_associado = ?', self.poder_associado)
			.select{|item| item.liquidacao.eh_processada? == false}

		return itens + itens_rp
	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 retorna_conselhos_de_rpps
		orcamento.conselhos_de_rpps.where('contabilidade_conselhos_de_rpps.arquivo_id is null').distinct.all
	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_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 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 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 retorna_alocacoes_de_recurso(poder_associado)
		orcamento.alocacoes_de_recurso_de_rpps.joins(orcamento: [unidades_orcamentarias: :tipo_de_unidade_administrativa]).where('base_tipos_de_unidades_administrativas.poder_associado = ?', poder_associado).distinct.all
	end

	def retorna_contas_extras(data_referencia, poder_associado)
		orcamento.contas_extra_orcamentarias.joins(orcamento: [unidades_orcamentarias: :tipo_de_unidade_administrativa]).where('contabilidade_contas_extra_orcamentarias.arquivo_id is null AND (contabilidade_contas_extra_orcamentarias.data_de_envio_pro_sim  BETWEEN ? AND ?) AND base_tipos_de_unidades_administrativas.poder_associado = ?', data_referencia, data_referencia.end_of_month, poder_associado).distinct.all
	end

	def retorna_unidades_gestoras(poder_associado)
		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

	def retorna_eventos_contabeis
		orcamento.eventos_contabeis.distinct.all
	end

	def retorna_orcamentos_da_despesa
		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}'")
		
		if self.mes_de_referencia == 'janeiro'
			iniciais = 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}")
			orcamentos_da_despesa.concat(iniciais) if iniciais.any?
		end
		return orcamentos_da_despesa
	end

	def retorna_elemento_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
	end

  def retorna_licitantes
    pessoa_do_projeto_ids = []
    Licitacao::ConfiguracaoSimDoProjeto.where('data_de_envio BETWEEN ? AND ?', self.data_referencia, self.data_referencia.end_of_month).each do |configuracao_sim|

      processo_id = configuracao_sim.projeto_id

      pessoas = Licitacao::PessoaDoProjeto.joins(projeto: [unidades_orcamentarias_por_pedido: [unidade_orcamentaria: :tipo_de_unidade_administrativa]])
        .where('licitacao_projetos.envia_pro_sim is TRUE AND licitacao_projetos.id = ?', processo_id)
        .where('base_tipos_de_unidades_administrativas.poder_associado = ?',self.poder_associado)
        .where('licitacao_projetos.data_de_envio_pro_sim BETWEEN ? AND ?', self.data_referencia, self.data_referencia.end_of_month)
        .where('licitacao_projetos.modalidade_do_processo != ? AND licitacao_projetos.status = ?', Licitacao::Projeto.modalidades_do_processo[:parceria_osc], Licitacao::Projeto.status[:homologado]).distinct.all

      pessoas.each do |pessoa|
        pessoa_do_projeto_ids << pessoa.id
      end
    end

    Licitacao::PessoaDoProjeto.where('id in (?)', pessoa_do_projeto_ids)
  end

	def retorna_licitantes_parcerias
		Licitacao::PessoaDoProjeto.joins(projeto: [unidades_orcamentarias_por_pedido: [unidade_orcamentaria: :tipo_de_unidade_administrativa]])
      .where('licitacao_projetos.envia_pro_sim is TRUE')
      .where('base_tipos_de_unidades_administrativas.poder_associado = ?',self.poder_associado)
			.where('licitacao_projetos.data_de_envio_pro_sim BETWEEN ? AND ?', self.data_referencia, self.data_referencia.end_of_month)
      .where('licitacao_projetos.modalidade_do_processo = ? AND licitacao_projetos.status = ?', Licitacao::Projeto.modalidades_do_processo[:parceria_osc], Licitacao::Projeto.status[:homologado]).distinct.all
	end

	def define_situacao
		self.com_erros! if criticas_do_modelo_do_sim.any?
	end

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

	def mes_de_geracao
		Tcm::ErrosDoLote.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 poder_associado
		Base::TipoDeUnidadeAdministrativa.poderes_associados[tipo_de_poder]
	end

end