class Contabilidade::MovimentacaoDoPlanoDeContas < ApplicationRecord
	#has_paper_trail

	attr_accessor :grupo_de_evento_id
	attr_accessor :evento_contabil_id
	attr_accessor :exercicio
	attr_accessor :conta_debito_id
	attr_accessor :conta_credito_id
	attr_accessor :criar_nova_subconta
	attr_accessor :descricao_subconta
	attr_accessor :grupo_pcasp
	attr_accessor :skip_callback
	attr_accessor :skip_geracao_credito
	attr_accessor :skip_validacao_sim
	attr_accessor :ic_fp_credito
	attr_accessor :ic_nr_credito
	attr_accessor :ic_nd_credito
	attr_accessor :ic_fs_credito
	attr_accessor :fonte_de_recursos_credito_id

	attr_default :skip_callback, false
	attr_default :skip_geracao_credito, false
	attr_default :skip_validacao_sim, false
	attr_default :criar_nova_subconta, false

	belongs_to :gerador, polymorphic: true
	belongs_to :conta_por_evento_contabil
	belongs_to :unidade_orcamentaria, class_name: "Loa::UnidadeOrcamentaria"
	belongs_to :movimentacao_par, class_name: "Contabilidade::MovimentacaoDoPlanoDeContas"
	belongs_to :conta_bancaria, class_name: "Base::ContaBancaria"
	belongs_to :centro_de_custo, class_name: "Controladoria::CentroDeCusto"
	belongs_to :sub_conta_pcasp, class_name: "Contabilidade::SubContaPcasp"
	belongs_to :fonte_de_recursos, class_name: "Base::FonteDeRecursos"
	belongs_to :conta_extra_orcamentaria, class_name: "Contabilidade::ContaExtraOrcamentaria", required: false

	has_many :movimentacoes_das_contas_do_balancete, class_name: "Contabilidade::MovimentacaoDaContaDoBalancete", dependent: :destroy
	has_many :movimentacoes_por_fonte_de_recursos, class_name: "Contabilidade::MovimentacaoPorFonteDeRecursos", dependent: :destroy

	has_one :evento_contabil, through: :conta_por_evento_contabil

	delegate :grupo_de_evento_contabil, to: :evento_contabil, allow_nil: true

	before_create :setar_codigo_da_conta

	validates_presence_of :conta_por_evento_contabil_id, :valor, :data_de_lancamento, :tipo_de_lancamento

	validates_presence_of :historico, :unidade_orcamentaria_id, :categoria_de_lancamento, if: Proc.new { lancamento_manual.present? && !self.transferencia_de_saldo_pcasp? && !self.encerramento? && !self.pre_encerramento?}
	validates_presence_of :grupo_de_evento_id, if: Proc.new { lancamento_manual.present? && !self.abertura_ou_encerramento? && !self.transferencia_de_saldo_pcasp? && !self.encerramento? && !self.pre_encerramento?}
	validates_presence_of :titulo, if: Proc.new { divida_ativa? }
	validates_presence_of :evento_contabil_id, if: Proc.new { exercicio.present? }
	validates_presence_of :sub_conta_pcasp_id, if: Proc.new { self.lancamento_manual.present? && !self.abertura? && !self.abertura_ou_encerramento? && !self.transferencia_de_saldo_pcasp?}
	#validates_presence_of :centro_de_custo_id, if: Proc.new { self.almoxarifado? }

	validates :gerador_id, immutable: true
	validates :gerador_type, immutable: true
	validate :valida_se_ja_houve_envio_do_sim, if: Proc.new { codigo_movimentacao.nil? && lancamento_manual.present? }
	validate :valida_se_ja_houve_geracao_do_balancete, if: Proc.new { codigo_movimentacao.nil? && lancamento_manual.present? }
	validate :valida_ics_debito, if: proc { lancamento_manual.present? && !self.skip_validacao_sim && self.debito? && !self.transferencia_de_saldo_pcasp? && !self.encerramento? && !self.pre_encerramento? }
	validate :valida_ics_credito, if: proc { lancamento_manual.present? && !self.skip_validacao_sim && self.debito? && !self.transferencia_de_saldo_pcasp? && !self.encerramento? && !self.pre_encerramento? } # TAMBÉM SÓ VALIDA NO DEBITO (POIS É O PRIMEIRO A GERAR PELO FORMULÁRIO)
	#validate :valida_se_mes_esta_bloqueado, if: Proc.new { codigo_movimentacao.nil? && lancamento_manual.present? }

	validate :verifica_se_a_subconta_esta_inativa

	before_create :atribui_codigo, if: Proc.new { codigo_movimentacao.nil? && lancamento_manual.present? && self.skip_callback == false }

	before_save :preenche_ics_da_movimentacao_manual, if: Proc.new { lancamento_manual.present? && !self.transferencia_de_saldo_pcasp? && !self.encerramento? && !self.pre_encerramento? }
	before_save :pesquisa_movimentacao_par, if: proc { credito? && !lancamento_manual.present? && self.movimentacao_par_id.nil? && self.skip_callback == false }
	before_save :gera_movimentacao_creditos, if: Proc.new { debito? && lancamento_manual.present? && !self.encerramento? && !self.pre_encerramento? && self.skip_callback == false && self.skip_geracao_credito == false }

	before_update :desfaz_movimentacao_nas_contas, if: Proc.new{ lancamento_manual.present? && self.skip_callback == false }
	before_update :desfaz_alteracoes_nos_saldos_das_diarias, if: Proc.new{ lancamento_manual.present? && self.skip_callback == false}

	# after_update :movimenta_saldo_da_conta, if: Proc.new{ lancamento_manual.present? }
	# after_update :atualiza_saldo_diario_da_conta, if: Proc.new { lancamento_manual.present? }

	# after_create :movimenta_saldo_da_conta, if: Proc.new{|objeto| objeto.conta_por_evento_contabil_id.present?}
	# after_create :atualiza_saldo_diario_da_conta, if: Proc.new{|objeto| objeto.conta_por_evento_contabil_id.present?}

	before_create :preenche_campos_ics, if: Proc.new {self.skip_callback == false }
	before_create :atribui_conta_bancaria, if: Proc.new{self.conta_bancaria_id.nil? && (conta_por_evento_contabil.conta.codigo[0..4] == '11111' || conta_por_evento_contabil.conta_par.codigo[0..4] == '11111') && self.skip_callback == false}

	# before_destroy :desfaz_movimentacao_no_saldo_da_conta, if: Proc.new{|objeto| objeto.conta_por_evento_contabil_id.present? }
	# before_destroy :desfaz_alteracao_no_saldo_diario_da_conta, if: Proc.new{|objeto| objeto.conta_por_evento_contabil_id.present? }

	before_destroy :valida_se_existe_empenho_associado_ao_movimento, if: Proc.new {lancamento_manual.present? && precatorio? && self.skip_callback == false }
	# before_destroy :valida_se_existe_empenho_associado_ao_movimento_erro
	after_destroy :deleta_movimentacao_par, if: Proc.new{ movimentacao_par.present? && self.skip_callback == false}

	before_validation :atribui_tipo_de_lancamento, on: :create, if: Proc.new{ tipo_de_lancamento.nil? && self.skip_callback == false}
	before_validation :atribui_conta_por_evento_contabil, on: :create, if: Proc.new{ debito? && (mudou_de_evento? || exercicio.present?) && self.skip_callback == false}
	before_validation :atribui_valor, if: Proc.new{ valor.nil? && gerador.present? && self.skip_callback == false}
	before_validation :atribui_data_de_lancamento, if: Proc.new{ data_de_lancamento.nil? && gerador.present? && self.skip_callback == false}

	#before_validation :cria_e_ou_atribui_sub_conta_pcasp_almoxarifado, if: Proc.new{ self.almoxarifado? }

	after_initialize :define_atributos, if: Proc.new{ persisted? && defined?(self.lancamento_manual) && lancamento_manual.present? && self.skip_callback == false}

	before_create :setar_codigo_completo_da_fonte, :setar_codigo_do_sub_elemento, :setar_conta_extra_orcamentaria
	before_update :setar_codigo_completo_da_fonte, :setar_codigo_do_sub_elemento, :setar_conta_extra_orcamentaria

	enum tipo_de_lancamento: {
		debito: 0,
		credito: 1
	}

	enum categoria_de_lancamento: {
		regular: 1,
		estorno: 2,
		circulante_para_nao_circulante: 3,
		nao_circulante_para_circulante: 4
	}

	enum titulo: {
		tributaria: 1,
		nao_tributaria: 2
	}

	enum lancamento_manual: {
		divida_ativa: 1,
		almoxarifado: 2,
		precatorio: 3,
		provisoes: 4,
		imobilizado: 5,
		rpps: 6,
		operacao_de_credito: 7,
		investimentos: 8,
    obrigacoes: 9,
		transferencia_de_saldo_pcasp: 900,
		abertura: 999,
		encerramento: 1000,
		pre_encerramento: 1001
	}

	enum grupo_pcasp: {
		circulante: 1,
		nao_circulante: 2
	}

	scope :sem_encerramento, -> { where("coalesce(contabilidade_movimentacoes_do_plano_de_contas.lancamento_manual, 0) != 1000") }
	scope :encerramento, -> { where("coalesce(contabilidade_movimentacoes_do_plano_de_contas.lancamento_manual, 0) in (1000, 1001)") }

	#ransacker :codigo_movimentacao do
	#	Arel.sql("(SELECT contabilidade_taloes_de_receita.numero_do_talao::integer FROM contabilidade_movimentacoes_do_plano_de_contas
	#						INNER JOIN contabilidade_taloes_de_receita
	#						ON contabilidade_taloes_de_receita.id = contabilidade_movimentacoes_do_plano_de_contas.gerador_id LIMIT 1)")
	#end

	def mes_bloqueado?
		orc = Orcamento.find_by(exercicio: self.data_de_lancamento.year)

		if orc.present? && self.data_de_lancamento.present?
			Contabilidade::BloqueioMensalDoPcasp.find_by(mes_referencia: self.data_de_lancamento&.month, orcamento_id: self.orcamento_id, bloqueado: true).present?
		else
			return false
		end
	end
	def gera_movimentacao_creditos
		deleta_movimentacao_par
		movimento_credito = self.dup
		movimento_credito.tipo_de_lancamento = 'credito'
		movimento_credito.movimentacao_par_id = nil
		movimento_credito.conta_por_evento_contabil_id = evento_contabil.contas_por_eventos_contabeis.find_by(tipo_de_lancamento: 'credito').try(:id)

		movimento_credito.ic_fp = nil if self.ic_fp_credito.blank?
		movimento_credito.ic_nr = nil if self.ic_nr_credito.blank?
		movimento_credito.ic_nd = nil if self.ic_nd_credito.blank?
		movimento_credito.ic_fs = nil if self.ic_fs_credito.blank?
		movimento_credito.ic_po = poder_ou_orgao_formatado
		if self.conta_par.informacao_complementar_possui_divida_consolidada?
			movimento_credito.ic_dc = (conta_par.codigo == "212110205" || (sub_conta_pcasp.present? && !sub_conta_pcasp&.divida_consolidada?)) ? '1' : nil 
		end

		if fonte_de_recursos_credito_id.present? && self.conta_par.informacao_complementar_possui_fonte_de_recursos?
			fonte_de_recurso_credito = self.evento_contabil.orcamento.fontes_de_recursos.find_by(id: self.fonte_de_recursos_credito_id)
			if fonte_de_recurso_credito.present?
				movimento_credito.fonte_de_recursos_id = fonte_de_recurso_credito.id
				codigo_completo = fonte_de_recurso_credito.codigo_completo rescue nil
				if codigo_completo.present?
					movimento_credito.ic_fr = fonte_de_recurso_credito.codigo_completo.first(4)
					if self.conta_par.informacao_complementar_possui_complemento_de_fonte?
						movimento_credito.ic_co = codigo_completo[4..7] if self.conta_par.informacao_complementar_possui_complemento_de_fonte?
					end
				end
			end
		end

		movimento_credito.save!
		self.movimentacao_par_id = movimento_credito.id
	end

	def conta
		conta_por_evento_contabil.conta rescue nil
	end

	def conta_par
		conta_por_evento_contabil.conta_par rescue nil
	end

	def abertura_ou_encerramento?
		self.abertura? || self.encerramento? || self.pre_encerramento?
	end

	def descricao_da_movimentacao
		if self.abertura? 
			"Abertura do Exercício (#{self.try(:evento_contabil).try(:modelo_i18n)}) #{self.try(:codigo_movimentacao)}"
		elsif self.encerramento? || self.pre_encerramento?
			"Encerramento do Exercício (#{self.try(:evento_contabil).try(:modelo_i18n)}) #{self.try(:codigo_movimentacao)}"
		else
			case gerador_type
			when "Contabilidade::Empenho"
				"#{self.try(:evento_contabil).try(:modelo_i18n).upcase} #{self.try(:codigo_movimentacao)} (ID: #{self.try(:gerador).try(:id)}) - Movimento gerado pela nota de empenho #{self.try(:codigo_movimentacao)}"
			when "Contabilidade::TalaoDeReceita"
				"#{self.try(:evento_contabil).try(:modelo_i18n).upcase} #{self.try(:codigo_movimentacao)} (ID: #{self.try(:gerador).try(:id)}) - #{self.try(:gerador).try(:historico)}"
			when "Contabilidade::Pagamento"
				self.try(:gerador).try(:resto_a_pagar) ? "#{self.try(:evento_contabil).try(:modelo_i18n).upcase} RP #{self.try(:codigo_movimentacao)} (ID: #{self.try(:gerador).try(:id)}) - #{self.try(:gerador).try(:historico)}" : "#{self.try(:evento_contabil).try(:modelo_i18n).upcase} #{self.try(:codigo_movimentacao)} (ID: #{self.try(:gerador).try(:id)}) - #{self.try(:gerador).try(:historico)}"
			when "Contabilidade::Liquidacao"
				if self.try(:gerador).try(:restos_a_pagar?)
					"#{self.try(:evento_contabil).try(:modelo_i18n).upcase} RP #{self.try(:gerador).try(:ano_de_competencia)} / #{self.try(:gerador).try(:empenho_e_numero)} (ID: #{self.try(:gerador).try(:id)}) - Movimento gerado pela Liquidação RP #{self.try(:gerador).try(:ano_de_competencia)} / #{self.try(:gerador).try(:empenho_e_numero)}"
				else
					"#{self.try(:evento_contabil).try(:modelo_i18n).upcase} #{self.try(:gerador).try(:empenho_e_numero)} (ID: #{self.try(:gerador).try(:id)}) - Movimento gerado pela Liquidação #{self.try(:gerador).try(:empenho_e_numero)}"
				end			
			else
				"#{self.try(:evento_contabil).try(:modelo_i18n).upcase} #{self.try(:codigo_movimentacao)} (ID: #{self.try(:gerador).try(:id)})"
			end
		end
	end

	def codigo_da_conta_e_numero
		"#{conta.codigo_formatado} #{self.codigo_movimentacao}"
	end

	def setar_codigo_da_conta
		self.codigo_da_conta = self.conta_por_evento_contabil.conta.codigo
	end

	def usa_sub_conta?
		usa_sub_conta = false

		if self.gerador.present? && self.gerador.class.name == "Contabilidade::TalaoDeReceita" && self.gerador.natureza_da_receita.present?
			usa_sub_conta = true if self.gerador.natureza_da_receita.categoria_economica == "002" && self.gerador.natureza_da_receita.origem == "1" || self.gerador.natureza_da_receita.detalhamento_optativo == "3"
		end

		return usa_sub_conta
	end

	def self.tipos_de_movimentacoes
		{
			"Empenho": "Contabilidade::Empenho",
			"Anulação de Empenho": "Contabilidade::AnulacaoDoEmpenho",
			"Liquidação": "Contabilidade::Liquidacao",
			"Estorno de Liquidação": "Contabilidade::EstornoDeLiquidacao",
			"Pagamento": "Contabilidade::Pagamento",
			"Estorno de Pagamento": "Contabilidade::EstornoDePagamento",
			"Talão de Receita": "Contabilidade::TalaoDeReceita",
			"Anulação de Talão de Receita": "Contabilidade::AnulacaoDoTalaoDeReceita",
			"Despesa Extraorçamentária": "Contabilidade::DespesaExtraOrcamentaria",
			"Anulação de Despesa Extraorçamentária": "Contabilidade::EstornoDeDespesaExtraOrcamentaria",
			"Lançamento Manual": "Contabilidade::LancamentoManualDoEventoContabil",
			"Lançamendo de Entrada": "GestaoDeEstoque::RecebimentoDeMaterial",
			"Lançamendo de Saída": "Administrativo::RequisicaoDeMaterial",
			"Pagamento da Retenção": "Contabilidade::PagamentoDaRetencao"
		}
	end

	def descricao_tipo_de_movimentacao
		case gerador_type
		when "Contabilidade::Empenho"
			"Empenho"
		when "Contabilidade::Liquidacao"
			"Liquidação"
		when "Contabilidade::Pagamento"
			"Pagamento"
		when "Contabilidade::TalaoDeReceita"
			"Talão de Receita"
		when "Contabilidade::EstornoDeLiquidacao"
			"Estorno de Liquidação"
		when "Contabilidade::EstornoDePagamento"
			"Estorno de Pagamento"
		when "Contabilidade::AnulacaoDoEmpenho"
			"Anulação de Empenho"
		when "Contabilidade::AnulacaoDoTalaoDeReceita"
			"Anulação de Talão de Receita"
		when "Contabilidade::DespesaExtraOrcamentaria"
			"Despesa Extraorçamentária"
		when "Contabilidade::EstornoDeDespesaExtraOrcamentaria"
			"Anulação de Despesa Extraorçamentária"
		when "Contabilidade::LancamentoManualDoEventoContabil"
			"Lançamento Manual"
		when "GestaoDeEstoque::RecebimentoDeMaterial"
			"Lançamendo de Entrada"
		when "Administrativo::RequisicaoDeMaterial"
			"Lançamendo de Saída"
		when "Contabilidade::MedicaoDaObra"
			"Reconhecimento de Medição de Obra"
		when "Contabilidade::Obra"
			"Obra"
		when "Contabilidade::SituacaoDaObra"
			"Situação da Obra"
		when "Contabilidade::BloqueioDeDotacao"
			"Bloqueio de Dotação"
		when "Contabilidade::SolicitacaoDeAlteracaoOrcamentaria"
			"Alteração Orcamentária"
		when "Contabilidade::PagamentoDaRetencao"
			"Pagamento da Retenção"
		else
			"Manual"
		end
	end

	def historico_por_tipo_de_movimentacao
		case gerador_type
		when "Contabilidade::Empenho"
			return self.gerador&.historico
		when "Contabilidade::Liquidacao"
			return self.gerador&.historico
		when "Contabilidade::Pagamento"
			return self.gerador&.historico
		when "Contabilidade::TalaoDeReceita"
			return self.gerador&.historico
		when "Contabilidade::EstornoDeLiquidacao"
			return self.gerador&.justificativa
		when "Contabilidade::EstornoDePagamento"
			return self.gerador&.justificativa
		when "Contabilidade::AnulacaoDoEmpenho"
			return self.gerador&.historico
		when "Contabilidade::AnulacaoDoTalaoDeReceita"
			return self.gerador&.historico
		when "Contabilidade::DespesaExtraOrcamentaria"
			return self.gerador&.historico
		when "Contabilidade::EstornoDeDespesaExtraOrcamentaria"
			return self.gerador&.justificativa
		when "Contabilidade::LancamentoManualDoEventoContabil"
			return self.gerador&.historico
		when "GestaoDeEstoque::RecebimentoDeMaterial"
			return self.gerador&.observacao
		when "Administrativo::RequisicaoDeMaterial"
			return self.gerador&.historico
		when "Contabilidade::MedicaoDaObra"
			return self.gerador&.historico
		when "Contabilidade::Obra"
			return self.gerador&.descricao
		when "Contabilidade::SituacaoDaObra"
			return self.gerador&.historico
		when "Contabilidade::BloqueioDeDotacao"
			return self.gerador&.justificativa
		when "Contabilidade::SolicitacaoDeAlteracaoOrcamentaria"
			return self.gerador&.justificativa
		when "Contabilidade::PagamentoDaRetencao"
			return self.gerador&.paagamento&.historico
		else
			"Manual"
		end
	end

	def link_to_gerador
		if movimentacao.gerador_type.eql?("Contabilidade::LancamentoManualDoEventoContabil")
			gerador.evento_contabil
		else
			gerador
		end
	end

	def detalhamento_da_conta
		movimentacao = self || movimentacao_par
		if movimentacao.gerador_type.eql?("Contabilidade::Empenho") || movimentacao.gerador_type.eql?("Contabilidade::AnulacaoDoEmpenho") ||
				movimentacao.gerador_type.eql?("Contabilidade::EstornoDeLiquidacao") || movimentacao.gerador_type.eql?("Contabilidade::Liquidacao") ||
					movimentacao.gerador_type.eql?("Contabilidade::Pagamento") || movimentacao.gerador_type.eql?("Contabilidade::EstornoDePagamento")
			"#{gerador.detalhamento_do_plano_de_contas} #{self.codigo_movimentacao}"
		elsif movimentacao.gerador_type.eql?("GestaoDeEstoque::RecebimentoDeMaterial")
			"#{gerador.detalhamento_do_plano_de_contas(conta_por_evento_contabil)}"
		else
			codigo_da_conta_e_numero
		end
	end

	def atribui_tipo_de_lancamento
		self.tipo_de_lancamento = 'debito'
	end

	def atribui_conta_por_evento_contabil
		evento_contabil = Contabilidade::EventoContabil.find_by(id: evento_contabil_id)

		if evento_contabil.present?
			self.conta_por_evento_contabil_id = evento_contabil.contas_por_eventos_contabeis.find_by(tipo_de_lancamento: 'debito').try(:id)
		end
	end

	def preenche_ics_da_movimentacao_manual
		self.ic_fp = nil if self.ic_fp.blank?
		self.ic_fr = nil if self.ic_dc.blank?
		self.ic_nr = nil if self.ic_nr.blank?
		self.ic_nd = nil if self.ic_nd.blank?
		self.ic_fs = nil if self.ic_fs.blank?

		self.ic_po = poder_ou_orgao_formatado
		self.ic_dc = codigo_divida_consolidada if ((self.conta.informacao_complementar_possui_divida_consolidada? && !self.ic_dc.present?) || self&.sub_conta_pcasp&.divida_consolidada?)
		self.ic_co = codigo_acompanhamento_formatado if self.conta.informacao_complementar_possui_complemento_de_fonte? && (!self.ic_co.present? || ic_co == '0000')

		self.ic_fr = self.fonte_de_recursos.codigo_completo.first(4) rescue nil
	end
	
	def pesquisa_movimentacao_par
		self.movimentacao_par_id = self.gerador.movimentacoes_do_plano_de_contas.order(:id).where(tipo_de_lancamento: :debito, valor: self.valor).last.try(:id)
	end

	def tipo_de_lancamento_inverso
		debito? ? 'credito' : 'debito'
	end

	def descricao_formatada
		"#{numero_do_processo_judicial.to_s} | #{valor.real_contabil}"
	end

	def descricao_formatada_subconta
		"#{sub_conta_pcasp.try(:codigo_e_descricao).to_s} | #{valor.real_contabil}"
	end

	def nome_do_evento_e_valor
		"#{evento_contabil.try(:nome).to_s} | #{valor.real_contabil}"
	end

	def conta_pcasp_passivo
		"#{self&.conta_por_evento_contabil&.conta&.codigo_formatado_e_nome}"
	end
	
	def poder_ou_orgao_formatado
		return '20231' unless unidade_orcamentaria.try(:tipo_de_unidade_administrativa).try(:executivo?)

		unidade_orcamentaria.rpps? ? '10132' : '10131'
	end

	def get_fonte_de_recursos
		case gerador_type
		when 'Contabilidade::Empenho'
			gerador.fonte_de_recursos
		when 'Contabilidade::Liquidacao', 'Contabilidade::Pagamento'
			gerador.empenho.fonte_de_recursos
		when 'Contabilidade::TalaoDeReceita'
			if gerador.try(:extra_orcamentario?)
				if gerador.pagamento.present?
					fonte_do_pagamento = gerador.pagamento.empenho.fonte_de_recursos rescue nil
					if gerador.extra_orcamentario?
						# chamado #4588 IPC 11
						if fonte_do_pagamento.present? && self.gerador.orcamento.exercicio >= 2025
							if fonte_do_pagamento.fonte_stn.recursos_do_exercicio_corrente?
								fonte_do_pagamento = self.gerador.orcamento.fontes_de_recursos.select { |i| i.codigo_completo == '1869000000' }.first
							elsif fonte_do_pagamento.fonte_stn.recursos_do_exercicio_corrente?
								fonte_do_pagamento = self.gerador.orcamento.fontes_de_recursos.select { |i| i.codigo_completo == '2869000000' }.first
							end
						end
					end
					return fonte_do_pagamento
				elsif gerador.pagamento_da_retencao.present?
					gerador.pagamento_da_retencao.retencao.pagamento.empenho.fonte_de_recursos rescue nil
				else
					gerador.fonte_de_recursos rescue nil
				end
			else
				valor_do_talao = gerador.natureza_da_receita.try(:deducao?) ? self.valor * -1 : self.valor
				gerador.complementos_por_fonte_do_talao_de_receita.where(valor: valor_do_talao).first.try(:fonte_de_recursos)
			end
		when 'Contabilidade::AnulacaoDoTalaoDeReceita'
			if gerador&.talao_de_receita.try(:extra_orcamentario?)
				if gerador&.talao_de_receita.pagamento.present?
					fonte_do_pagamento = gerador&.talao_de_receita.pagamento.empenho.fonte_de_recursos rescue nil
					if gerador&.talao_de_receita.extra_orcamentario?
						# chamado #4588 IPC 11
						if fonte_do_pagamento.present? && self.gerador&.talao_de_receita.orcamento.exercicio >= 2025
							if fonte_do_pagamento.fonte_stn.recursos_do_exercicio_corrente?
								fonte_do_pagamento = self.gerador&.talao_de_receita.orcamento.fontes_de_recursos.select { |i| i.codigo_completo == '1869000000' }.first
							elsif fonte_do_pagamento.fonte_stn.recursos_do_exercicio_corrente?
								fonte_do_pagamento = self.gerador&.talao_de_receita.orcamento.fontes_de_recursos.select { |i| i.codigo_completo == '2869000000' }.first
							end
						end
					end

					return fonte_do_pagamento
				elsif gerador&.talao_de_receita.pagamento_da_retencao.present?
					gerador&.talao_de_receita.pagamento_da_retencao.retencao.pagamento.empenho.fonte_de_recursos rescue nil
				else
					gerador&.talao_de_receita.fonte_de_recursos rescue nil
				end
			else
				valor_do_talao = gerador.talao_de_receita.natureza_da_receita.try(:deducao?) ? self.valor * -1 : self.valor
				gerador.complementos_por_fonte_da_anulacao_do_talao.where(valor: valor_do_talao).first.try(:fonte_de_recursos)
			end
		when 'Base::ContaBancaria'
			gerador.fontes_de_recursos_da_conta_bancaria.where("saldo_inicial > 0").first.try(:fonte_de_recurso) rescue nil
		when 'Contabilidade::DespesaExtraOrcamentaria'
			if gerador.pagamento_da_retencao.present?
				if gerador.pagamento_da_retencao.pagamento.orcamento.exercicio >= 2025
					if gerador.pagamento_da_retencao.pagamento.empenho.fonte_de_recursos.fonte_stn.recursos_do_exercicio_corrente?
						gerador.pagamento_da_retencao.pagamento.orcamento.fontes_de_recursos.select { |i| i.codigo_completo == '1869000000' }.first rescue nil
					else
						gerador.pagamento_da_retencao.pagamento.orcamento.fontes_de_recursos.select { |i| i.codigo_completo == '2869000000' }.first rescue nil
					end
				else
					gerador.pagamento_da_retencao.pagamento.empenho.fonte_de_recursos rescue nil
				end
			else
				gerador.fonte_de_recursos rescue nil
			end
		when 'Contabilidade::EstornoDeDespesaExtraOrcamentaria'
			if gerador.despesa_extra_orcamentaria.pagamento_da_retencao.pagamento.present?
				if gerador.despesa_extra_orcamentaria.pagamento_da_retencao.pagamento.orcamento.exercicio >= 2025
					if gerador.despesa_extra_orcamentaria.pagamento_da_retencao.pagamento.empenho.fonte_de_recursos.fonte_stn.recursos_do_exercicio_corrente?
						gerador.despesa_extra_orcamentaria.pagamento_da_retencao.pagamento.orcamento.fontes_de_recursos.select { |i| i.codigo_completo == '1869000000' }.first rescue nil
					else
						gerador.despesa_extra_orcamentaria.pagamento_da_retencao.pagamento.orcamento.fontes_de_recursos.select { |i| i.codigo_completo == '2869000000' }.first rescue nil
					end
				else
					gerador.despesa_extra_orcamentaria.pagamento_da_retencao.pagamento.empenho.fonte_de_recursos rescue nil
				end
			else
				gerador.despesa_extra_orcamentaria.pagamento_da_retencao.pagamento.empenho.fonte_de_recursos rescue nil
			end
		when 'Contabilidade::CancelamentoDeRestoAPagar'
			gerador.restos_a_pagar_cancelados.where(valor_cancelado: self.valor).first.empenho.fonte_de_recursos rescue nil
		when "Contabilidade::BloqueioDeDotacao"
			gerador.orcamento_da_despesa.fonte_de_recursos rescue nil
		end
	end

	def codigo_superavit_financeiro
		if conta.codigo[0] == '2' && self.gerador.present?
			if gerador_type == 'Contabilidade::TalaoDeReceita'
				self.gerador.operacao_de_credito ? '2' : '1'
			else
				'1'
			end
		else
			conta.financeira? || conta.ambos? ? '1' : '2'
		end
	end

	def codigo_acompanhamento_formatado
		complemento = get_fonte_de_recursos.codigo_completo[4..7] rescue nil

		if complemento.to_i == 0 
			case gerador_type
			when 'Contabilidade::Empenho'
				complemento = Contabilidade::Empenho.complementacao_da_fonte_de_recursos[gerador.complementacao_da_fonte_de_recurso].to_s rescue nil
			when 'Contabilidade::AnulacaoDoTalaoDeReceita'
				valor_do_talao = gerador.talao_de_receita.natureza_da_receita.try(:deducao?) ? self.valor * -1 : self.valor
				complemento_por_fonte = gerador.complementos_por_fonte_do_talao_de_receita.where(valor: valor_do_talao).first rescue nil

				complemento = Contabilidade::ComplementoPorFonteDaAnulacaoDoTalao.complementacao_da_fonte_de_recursos[complemento_por_fonte.complementacao_da_fonte_de_recurso].to_s rescue nil
			when 'Contabilidade::TalaoDeReceita'
				valor_do_talao = gerador.natureza_da_receita.try(:deducao?) ? self.valor * -1 : self.valor
				complemento_por_fonte = gerador.complementos_por_fonte_do_talao_de_receita.where(valor: valor_do_talao).first rescue nil

				complemento = Contabilidade::ComplementoPorFonteDaAnulacaoDoTalao.complementacao_da_fonte_de_recursos[complemento_por_fonte.complementacao_da_fonte_de_recurso].to_s rescue nil
			end
		end

		if complemento.to_i == 0 or complemento.to_s == '0000'
			complemento = nil
		end
		
		complemento
	end

	def codigo_fonte_de_recursos_formatado
		self.fonte_de_recursos = get_fonte_de_recursos
		self.fonte_de_recursos.codigo_completo.first(4) rescue nil
	end

	def setar_codigo_completo_da_fonte
		self.codigo_completo_fr = self.fonte_de_recursos&.codigo_completo
	end

	def setar_codigo_do_sub_elemento
		unless self.gerador_type == "Loa::OrcamentoDaDespesa" || self.gerador_type == "Contabilidade::BloqueioDeDotacao"
			if gerador.respond_to?(:sub_elemento_de_despesa) && gerador&.sub_elemento_de_despesa&.present?
				gerador.sub_elemento_de_despesa.codigo_completo[6..7] rescue nil
			end
		end
	end

	def setar_conta_extra_orcamentaria
		if self.gerador_type == 'Contabilidade::DespesaExtraOrcamentaria'
			self.conta_extra_orcamentaria_id = self.gerador&.conta_extra_orcamentaria_id
		elsif self.gerador_type == 'Contabilidade::EstornoDeDespesaExtraOrcamentaria'
			self.conta_extra_orcamentaria_id = self.gerador&.despesa_extra_orcamentaria&.conta_extra_orcamentaria_id
		elsif self.gerador_type == 'Contabilidade::TalaoDeReceita' && self.gerador&.origem_do_talao == "extra_orcamentario"
			self.conta_extra_orcamentaria_id = self.gerador&.conta_extra_orcamentaria_id
		elsif self.gerador_type == 'Contabilidade::AnulacaoDoTalaoDeReceita' && self.gerador&.talao_de_receita&.origem_do_talao == "extra_orcamentario"
			self.conta_extra_orcamentaria_id = self.gerador&.talao_de_receita&.conta_extra_orcamentaria_id
		end
	end

	def codigo_natureza_da_receita_formatada
		if gerador.natureza_da_receita.present?
			if gerador.natureza_da_receita.codigo[0..2] == '009' && gerador.natureza_da_receita.codigo[2..9] != '99900000'
				gerador.natureza_da_receita.codigo[4..11] rescue nil
			else
				gerador.natureza_da_receita.codigo[2..9] rescue nil
			end
		end
	end

	def codigo_natureza_da_despesa_formatada
		return nil if (self.gerador_type == "Contabilidade::MedicaoDaObra" || self.gerador_type == "Contabilidade::Obra" || self.gerador_type == "Contabilidade::CancelamentoDeRestoAPagar")

		if self.gerador_type == "Loa::OrcamentoDaDespesa"
			gerador.elemento_de_despesa_por_subacao.elemento_de_despesa.codigo
		elsif self.gerador_type == "Contabilidade::BloqueioDeDotacao"
			gerador.orcamento_da_despesa.elemento_de_despesa_por_subacao.elemento_de_despesa.codigo rescue nil
		else
			if gerador.sub_elemento_de_despesa.present?
				gerador.sub_elemento_de_despesa.codigo_do_objeto_para_msc rescue nil
				# if gerador.sub_elemento_de_despesa.nd_complementar.present?
				# 	gerador.sub_elemento_de_despesa.nd_complementar rescue nil
				# else
				# 	gerador.sub_elemento_de_despesa.codigo_completo rescue nil
				# end
			end
		end
	end

	def codigo_divida_consolidada
		(conta.codigo == "212110205" || !sub_conta_pcasp.divida_consolidada?) ? '1' : nil rescue nil
	end

	def codigo_ano_de_inscricao_resto_a_pagar
		case gerador_type
		when "Contabilidade::Empenho"
			gerador.orcamento.exercicio if gerador.restos_a_pagar
		when "Contabilidade::Liquidacao", "Contabilidade::Pagamento", "Contabilidade::EstornoDePagamento", "Contabilidade::EstornoDeLiquidacao"
			gerador.empenho.orcamento.exercicio if gerador.empenho.restos_a_pagar
		end
	end

	def codigo_funcao_e_subfuncao
		case gerador_type
		when "Contabilidade::Empenho", "Contabilidade::BloqueioDeDotacao"
			gerador.orcamento_da_despesa.subacao.funcao.codigo + gerador.orcamento_da_despesa.subacao.subfuncao.codigo rescue nil
		when "Contabilidade::Liquidacao", "Contabilidade::Pagamento", "Contabilidade::AnulacaoDoEmpenho", "Contabilidade::EstornoDePagamento", "Contabilidade::EstornoDeLiquidacao"
			gerador.empenho.orcamento_da_despesa.subacao.funcao.codigo + gerador.empenho.orcamento_da_despesa.subacao.subfuncao.codigo rescue nil
		when "Loa::OrcamentoDaDespesa"
			gerador.subacao.funcao.codigo + gerador.subacao.subfuncao.codigo rescue nil
		end
	end

	def unidade_orcamentaria_gerador
		unidade_orcamentaria || gerador.try(:unidade_orcamentaria)
	end

	def somatorio_por_subfuncao (funcao, subfuncoes)
		movimentacoes_por_subfuncao = []

		#Empenhos
		empenhos_de_movimentacao_ids = Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::Empenho" ).pluck(:gerador_id)
				
		empenhos_por_subfuncao_ids = Contabilidade::Empenho
		.joins(orcamento_da_despesa: [elemento_de_despesa_por_subacao: :subacao])
		.where("contabilidade_empenhos.id in (?)", empenhos_de_movimentacao_ids)
		.where("loa_subacoes.funcao_id in (?) AND loa_subacoes.subfuncao_id in (?)", funcao, subfuncoes).pluck(:id)
		
		if empenhos_por_subfuncao_ids.any?
			movimentacoes_por_subfuncao  = movimentacoes_por_subfuncao + Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::Empenho" ).where("gerador_id in (?)", empenhos_por_subfuncao_ids)
		end
		#Liquidacoes
		liquidacoes_de_movimentacao_ids = Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::Liquidacao" ).pluck(:gerador_id)
				
		liquidacoes_por_subfuncao_ids = Contabilidade::Liquidacao
		.joins(empenho: [orcamento_da_despesa: [elemento_de_despesa_por_subacao: :subacao]])
		.where("contabilidade_liquidacoes.id in (?)", liquidacoes_de_movimentacao_ids)
		.where("loa_subacoes.funcao_id in (?) AND loa_subacoes.subfuncao_id in (?)", funcao, subfuncoes).pluck(:id)
		
		if liquidacoes_por_subfuncao_ids.any?
			movimentacoes_por_subfuncao  = movimentacoes_por_subfuncao + Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::Liquidacao" ).where("gerador_id in (?)", liquidacoes_por_subfuncao_ids)
		end

		#Pagamentos
		pagamentos_de_movimentacao_ids = Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::Pagamento" ).pluck(:gerador_id)
				
		pagamentos_por_subfuncao_ids = Contabilidade::Pagamento
		.joins(liquidacao: [empenho: [orcamento_da_despesa: [elemento_de_despesa_por_subacao: :subacao]]])
		.where("contabilidade_pagamentos.id in (?)", pagamentos_de_movimentacao_ids)
		.where("loa_subacoes.funcao_id in (?) AND loa_subacoes.subfuncao_id in (?)", funcao, subfuncoes).pluck(:id)
		
		if pagamentos_de_movimentacao_ids.any?
			movimentacoes_por_subfuncao  = movimentacoes_por_subfuncao + Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::Pagamento" ).where("gerador_id in (?)", pagamentos_por_subfuncao_ids)
		end

		#Estorno De Liquidacao
		estornos_de_liquidacoes_de_movimentacao_ids = Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::EstornoDeLiquidacao" ).pluck(:gerador_id)
				
		estornos_de_liquidacoes_por_subfuncao_ids = Contabilidade::EstornoDeLiquidacao
		.joins(liquidacao: [empenho: [orcamento_da_despesa: [elemento_de_despesa_por_subacao: :subacao]]])
		.where("contabilidade_estornos_de_liquidacao.id in (?)", estornos_de_liquidacoes_de_movimentacao_ids)
		.where("loa_subacoes.funcao_id in (?) AND loa_subacoes.subfuncao_id in (?)", funcao, subfuncoes).pluck(:id)
		
		if estornos_de_liquidacoes_de_movimentacao_ids.any?
			movimentacoes_por_subfuncao  = movimentacoes_por_subfuncao + Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::EstornoDeLiquidacao" ).where("gerador_id in (?)", estornos_de_liquidacoes_por_subfuncao_ids)
		end

		#Estorno De Pagamento
		estorno_de_pagamentos_de_movimentacao_ids = Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::EstornoDePagamento" ).pluck(:gerador_id)
				
		estorno_de_pagamentos_por_subfuncao_ids = Contabilidade::EstornoDePagamento
		.joins(pagamento: [liquidacao: [empenho: [orcamento_da_despesa: [elemento_de_despesa_por_subacao: :subacao]]]])
		.where("contabilidade_estornos_de_pagamento.id in (?)", estorno_de_pagamentos_de_movimentacao_ids)
		.where("loa_subacoes.funcao_id in (?) AND loa_subacoes.subfuncao_id in (?)", funcao, subfuncoes).pluck(:id)
		
		if estorno_de_pagamentos_de_movimentacao_ids
			movimentacoes_por_subfuncao  = movimentacoes_por_subfuncao + Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::EstornoDePagamento" ).where("gerador_id in (?)", estorno_de_pagamentos_por_subfuncao_ids)
		end

		#AnulacaoDoEmpenho
		anulacoes_do_empenho_de_movimentacao_ids = Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::AnulacaoDoEmpenho" ).pluck(:gerador_id)
		
		anulacoes_do_empenho_por_subfuncao_ids = Contabilidade::AnulacaoDoEmpenho
		.joins(empenho: [orcamento_da_despesa: [elemento_de_despesa_por_subacao: :subacao]])
		.where("contabilidade_anulacoes_do_empenho.id in (?)", anulacoes_do_empenho_de_movimentacao_ids)
		.where("loa_subacoes.funcao_id in (?) AND loa_subacoes.subfuncao_id in (?)", funcao, subfuncoes).pluck(:id)
		
		if anulacoes_do_empenho_por_subfuncao_ids.any?
			movimentacoes_por_subfuncao  = movimentacoes_por_subfuncao + Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::AnulacaoDoEmpenho" ).where("gerador_id in (?)", anulacoes_do_empenho_por_subfuncao_ids)
		end

		return movimentacoes_por_subfuncao
	end

	def somatorio_por_funcao (funcao)
		movimentacoes_por_funcao = []

		#Empenhos
		empenhos_de_movimentacao_ids = Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::Empenho" ).pluck(:gerador_id)
				
		empenhos_por_funcao_ids = Contabilidade::Empenho
		.joins(orcamento_da_despesa: [elemento_de_despesa_por_subacao: :subacao])
		.where("contabilidade_empenhos.id in (?)", empenhos_de_movimentacao_ids)
		.where("loa_subacoes.funcao_id in (?)", funcao).pluck(:id)
		
		if empenhos_por_funcao_ids.any?
			movimentacoes_por_funcao  = movimentacoes_por_funcao + Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::Empenho" ).where("gerador_id in (?)", empenhos_por_funcao_ids)
		end
		#Liquidacoes
		liquidacoes_de_movimentacao_ids = Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::Liquidacao" ).pluck(:gerador_id)
				
		liquidacoes_por_funcao_ids = Contabilidade::Liquidacao
		.joins(empenho: [orcamento_da_despesa: [elemento_de_despesa_por_subacao: :subacao]])
		.where("contabilidade_liquidacoes.id in (?)", liquidacoes_de_movimentacao_ids)
		.where("loa_subacoes.funcao_id in (?)", funcao).pluck(:id)
		
		if liquidacoes_por_funcao_ids.any?
			movimentacoes_por_funcao  = movimentacoes_por_funcao + Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::Liquidacao" ).where("gerador_id in (?)", liquidacoes_por_funcao_ids)
		end

		#Pagamentos
		pagamentos_de_movimentacao_ids = Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::Pagamento" ).pluck(:gerador_id)
				
		pagamentos_por_funcao_ids = Contabilidade::Pagamento
		.joins(liquidacao: [empenho: [orcamento_da_despesa: [elemento_de_despesa_por_subacao: :subacao]]])
		.where("contabilidade_pagamentos.id in (?)", pagamentos_de_movimentacao_ids)
		.where("loa_subacoes.funcao_id in (?)", funcao).pluck(:id)
		
		if pagamentos_de_movimentacao_ids.any?
			movimentacoes_por_funcao  = movimentacoes_por_funcao + Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::Pagamento" ).where("gerador_id in (?)", pagamentos_por_funcao_ids)
		end

		#Estorno De Liquidacao
		estornos_de_liquidacoes_de_movimentacao_ids = Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::EstornoDeLiquidacao" ).pluck(:gerador_id)
				
		estornos_de_liquidacoes_por_funcao_ids = Contabilidade::EstornoDeLiquidacao
		.joins(liquidacao: [empenho: [orcamento_da_despesa: [elemento_de_despesa_por_subacao: :subacao]]])
		.where("contabilidade_estornos_de_liquidacao.id in (?)", estornos_de_liquidacoes_de_movimentacao_ids)
		.where("loa_subacoes.funcao_id in (?)", funcao).pluck(:id)
		
		if estornos_de_liquidacoes_de_movimentacao_ids.any?
			movimentacoes_por_funcao  = movimentacoes_por_funcao + Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::EstornoDeLiquidacao" ).where("gerador_id in (?)", estornos_de_liquidacoes_por_funcao_ids)
		end

		#Estorno De Pagamento
		estorno_de_pagamentos_de_movimentacao_ids = Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::EstornoDePagamento" ).pluck(:gerador_id)
				
		estorno_de_pagamentos_por_funcao_ids = Contabilidade::EstornoDePagamento
		.joins(pagamento: [liquidacao: [empenho: [orcamento_da_despesa: [elemento_de_despesa_por_subacao: :subacao]]]])
		.where("contabilidade_estornos_de_pagamento.id in (?)", estorno_de_pagamentos_de_movimentacao_ids)
		.where("loa_subacoes.funcao_id in (?)", funcao).pluck(:id)
		
		if estorno_de_pagamentos_de_movimentacao_ids
			movimentacoes_por_funcao  = movimentacoes_por_funcao + Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::EstornoDePagamento" ).where("gerador_id in (?)", estorno_de_pagamentos_por_funcao_ids)
		end

		#AnulacaoDoEmpenho
		anulacoes_do_empenho_de_movimentacao_ids = Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::AnulacaoDoEmpenho" ).pluck(:gerador_id)
		
		anulacoes_do_empenho_por_funcao_ids = Contabilidade::AnulacaoDoEmpenho
		.joins(empenho: [orcamento_da_despesa: [elemento_de_despesa_por_subacao: :subacao]])
		.where("contabilidade_anulacoes_do_empenho.id in (?)", anulacoes_do_empenho_de_movimentacao_ids)
		.where("loa_subacoes.funcao_id in (?)", funcao).pluck(:id)
		
		if anulacoes_do_empenho_por_funcao_ids.any?
			movimentacoes_por_funcao  = movimentacoes_por_funcao + Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Contabilidade::AnulacaoDoEmpenho" ).where("gerador_id in (?)", anulacoes_do_empenho_por_funcao_ids)
		end

		return movimentacoes_por_funcao
	end

	def codigo_da_subconta
		numero_do_processo_judicial || centro_de_custo.try(:descricao)
	end
	
	def regras_do_evento_de_acordo_com_o_gerador?
		valido = true

		return false unless natureza_da_receita_de_acordo_com_o_gerador?
		evento_contabil.campos_por_modelo_de_ativacao.each do |campo_por_modelo|
			case campo_por_modelo
			when :modalidade_do_empenho
				valido = modalidade_do_empenho_de_acordo_com_o_gerador?
			when :tipo_de_pessoa 
				valido = tipo_de_pessoa_de_acordo_com_o_gerador?
			when :uso_do_bem 
				valido = uso_do_bem_de_acordo_com_o_gerador?
			when :tipo_de_obra 
				valido = tipo_de_obra_de_acordo_com_o_gerador?
			when :conta_pcasp_da_conta_bancaria_id 
				valido = conta_pcasp_da_conta_bancaria_de_acordo_com_o_gerador?
			when :origem_da_retencao 
				valido = origem_da_retencao_de_acordo_com_o_gerador?
			when :tipo_de_credito 
				valido = tipo_de_credito_de_acordo_com_o_gerador?
			when :origem_do_recurso 
				valido = origem_do_recurso_de_acordo_com_o_gerador?
			when :cancelamento_por_falta_de_disponibilidade_de_caixa
				valido = cancelamento_por_falta_de_disponibilidade_de_caixa_de_acordo_com_o_gerador?
			when :empenho_complementar
				valido = empenho_complementar_de_acordo_com_o_gerador?
			when :resto_a_pagar 
				valido = resto_a_pagar_de_acordo_com_o_gerador?
			when :processado 
				valido = processado_de_acordo_com_o_gerador?
			when :receita_de_deducao
				valido = receita_de_deducao_de_acordo_com_o_gerador?
			when :bem_lancado
				valido = bem_lancado_de_acordo_com_o_gerador?
			when :obra_tombada
				valido = obra_tombada_de_acordo_com_o_gerador?
			when :veio_de_uma_ordem 
				valido = veio_de_uma_ordem_de_acordo_com_o_gerador?
			when :extraorcamentario 
				valido = extraorcamentario_de_acordo_com_o_gerador?
			when :originado_de_um_evento_manual 
				valido = originado_de_um_evento_manual_de_acordo_com_o_gerador?
			# when :com_fonte_de_recursos
			# 	valido = com_fonte_de_recursos_de_acordo_com_o_gerador?
			#when :tipo_de_resto_a_pagar 
			#	valido = tipo_de_resto_a_pagar_de_acordo_com_o_gerador?
			end

			return valido unless valido
		end

		return valido
	end

	def modalidade_do_empenho_de_acordo_com_o_gerador?
		gerador.modalidade_do_empenho_por_model.include?(evento_contabil.configuracao_do_evento_contabil.read_attribute_before_type_cast(:modalidade_do_empenho)) ||
		evento_contabil.configuracao_do_evento_contabil.modalidade_do_empenho.nil?
	end

	def tipo_de_pessoa_de_acordo_com_o_gerador?
		gerador.tipos_de_pessoa_por_model.include?(evento_contabil.configuracao_do_evento_contabil.read_attribute_before_type_cast(:tipo_de_pessoa)) ||
		evento_contabil.configuracao_do_evento_contabil.tipo_de_pessoa.nil?
	end

	def uso_do_bem_de_acordo_com_o_gerador?
		gerador.uso_do_bem_por_model == evento_contabil.configuracao_do_evento_contabil.read_attribute_before_type_cast(:uso_do_bem) ||
		evento_contabil.configuracao_do_evento_contabil.uso_do_bem.nil?
	end

	def tipo_de_obra_de_acordo_com_o_gerador?
		gerador.tipo_de_obra_por_model == evento_contabil.configuracao_do_evento_contabil.read_attribute_before_type_cast(:tipo_de_obra) ||
		evento_contabil.configuracao_do_evento_contabil.tipo_de_obra.nil?
	end

	def conta_pcasp_da_conta_bancaria_de_acordo_com_o_gerador?
		unless gerador.contas_pcasp_das_contas_bancarias_por_model.nil?
			gerador.contas_pcasp_das_contas_bancarias_por_model.pluck(:conta_id).include?(evento_contabil.configuracao_do_evento_contabil.conta_pcasp_da_conta_bancaria_id) ||
			evento_contabil.configuracao_do_evento_contabil.conta_pcasp_da_conta_bancaria_id.nil?
		end
	end

	def origem_da_retencao_de_acordo_com_o_gerador?
		gerador.origem_da_retencao_por_model == evento_contabil.configuracao_do_evento_contabil.read_attribute_before_type_cast(:origem_da_retencao) ||
		evento_contabil.configuracao_do_evento_contabil.origem_da_retencao.nil?
	end

	def tipo_de_credito_de_acordo_com_o_gerador?
		gerador.tipo_de_credito_por_model == evento_contabil.configuracao_do_evento_contabil.read_attribute_before_type_cast(:tipo_de_credito) ||
		evento_contabil.configuracao_do_evento_contabil.tipo_de_credito.nil?
	end

	def origem_do_recurso_de_acordo_com_o_gerador?
		gerador.origem_do_recurso_por_model == evento_contabil.configuracao_do_evento_contabil.read_attribute_before_type_cast(:origem_do_recurso) ||
		evento_contabil.configuracao_do_evento_contabil.origem_do_recurso.nil?
	end

	def tipo_de_resto_a_pagar_de_acordo_com_o_gerador?
		gerador.tipo_de_resto_a_pagar_por_model == evento_contabil.configuracao_do_evento_contabil.read_attribute_before_type_cast(:tipo_de_resto_a_pagar) ||
		evento_contabil.configuracao_do_evento_contabil.tipo_de_resto_a_pagar.nil?
	end

	def cancelamento_por_falta_de_disponibilidade_de_caixa_de_acordo_com_o_gerador?
		gerador.cancelamento_por_falta_de_disponibilidade_de_caixa_por_model == evento_contabil.configuracao_do_evento_contabil.cancelamento_por_falta_de_disponibilidade_de_caixa ||
		gerador.try(:indisponibilidade_de_caixa) == evento_contabil.configuracao_do_evento_contabil.cancelamento_por_falta_de_disponibilidade_de_caixa ||
		evento_contabil.configuracao_do_evento_contabil.cancelamento_por_falta_de_disponibilidade_de_caixa.nil? 
	end
	
	def empenho_complementar_de_acordo_com_o_gerador?
		gerador.empenho_complementar_por_model == evento_contabil.configuracao_do_evento_contabil.empenho_complementar ||
		evento_contabil.configuracao_do_evento_contabil.empenho_complementar.nil?
	end

	def resto_a_pagar_de_acordo_com_o_gerador?
		gerador.eh_resto_a_pagar_por_model == evento_contabil.configuracao_do_evento_contabil.resto_a_pagar ||
		evento_contabil.configuracao_do_evento_contabil.resto_a_pagar.nil?
	end

	def processado_de_acordo_com_o_gerador?
		gerador.resto_a_pagar_processado_por_model == evento_contabil.configuracao_do_evento_contabil.processado ||
		evento_contabil.configuracao_do_evento_contabil.processado.nil?
	end

	def receita_de_deducao_de_acordo_com_o_gerador?
		gerador.eh_receita_de_deducao_por_model == evento_contabil.configuracao_do_evento_contabil.receita_de_deducao ||
		evento_contabil.configuracao_do_evento_contabil.receita_de_deducao.nil? || gerador.eh_receita_de_deducao_por_model.nil?
	end

	def bem_lancado_de_acordo_com_o_gerador?
		gerador.bem_lancado_por_model == evento_contabil.configuracao_do_evento_contabil.bem_lancado ||
		evento_contabil.configuracao_do_evento_contabil.bem_lancado.nil?
	end

	def bem_lancado_de_acordo_com_o_gerador?
		gerador.bem_lancado_por_model == evento_contabil.configuracao_do_evento_contabil.bem_lancado ||
		evento_contabil.configuracao_do_evento_contabil.bem_lancado.nil?
	end

	def obra_tombada_de_acordo_com_o_gerador?
		gerador.obra_tombada_por_model == evento_contabil.configuracao_do_evento_contabil.obra_tombada ||
		evento_contabil.configuracao_do_evento_contabil.obra_tombada.nil?
	end

	def veio_de_uma_ordem_de_acordo_com_o_gerador?
		gerador.veio_de_uma_ordem_por_model == evento_contabil.configuracao_do_evento_contabil.veio_de_uma_ordem ||
		evento_contabil.configuracao_do_evento_contabil.veio_de_uma_ordem.nil?
	end

	def extraorcamentario_de_acordo_com_o_gerador?
		gerador.extraorcamentario_por_model == evento_contabil.configuracao_do_evento_contabil.extraorcamentario ||
		evento_contabil.configuracao_do_evento_contabil.extraorcamentario.nil?
	end

	def originado_de_um_evento_manual_de_acordo_com_o_gerador?
		gerador.originado_de_um_evento_manual_por_model == evento_contabil.configuracao_do_evento_contabil.originado_de_um_evento_manual ||
		evento_contabil.configuracao_do_evento_contabil.originado_de_um_evento_manual.nil?
	end

	# def com_fonte_de_recursos_de_acordo_com_o_gerador?
	# 	gerador.com_fonte_de_recursos_por_model == evento_contabil.configuracao_do_evento_contabil.com_fonte_de_recursos ||
	# 	evento_contabil.configuracao_do_evento_contabil.com_fonte_de_recursos.nil?
	# end

	def natureza_da_receita_de_acordo_com_o_gerador?
		return true if (gerador_type != "Contabilidade::TalaoDeReceita" && gerador_type != "Contabilidade::AnulacaoDoTalaoDeReceita") || (gerador_type == "Contabilidade::TalaoDeReceita" || gerador_type == "Contabilidade::AnulacaoDoTalaoDeReceita" && evento_contabil.configuracao_do_evento_contabil.naturezas_da_receita_da_configuracao_contabil.empty?)

		if (gerador_type == "Contabilidade::TalaoDeReceita" && gerador.orcamentario?) || (gerador_type == "Contabilidade::AnulacaoDoTalaoDeReceita" && gerador.talao_de_receita.orcamentario?)
			evento_contabil.configuracao_do_evento_contabil.naturezas_da_receita_da_configuracao_contabil.each do |natureza_da_configuracao|
				categoria_economica_de_acordo = natureza_da_configuracao.categoria_economica == "000" || natureza_da_configuracao.categoria_economica == gerador.natureza_da_receita.categoria_economica
				origem_de_acordo = natureza_da_configuracao.origem == "0" || natureza_da_configuracao.origem == gerador.natureza_da_receita.origem
				especie_de_acordo = natureza_da_configuracao.especie == "0" || natureza_da_configuracao.especie == gerador.natureza_da_receita.especie
				rubrica_de_acordo = natureza_da_configuracao.rubrica == "0" || natureza_da_configuracao.rubrica == gerador.natureza_da_receita.rubrica
				alinea_de_acordo = natureza_da_configuracao.alinea == "00" || natureza_da_configuracao.alinea == gerador.natureza_da_receita.alinea
				subalinea_de_acordo = natureza_da_configuracao.subalinea == "0" || natureza_da_configuracao.subalinea == gerador.natureza_da_receita.subalinea
				detalhamento_optativo_de_acordo = natureza_da_configuracao.detalhamento_optativo == "0" || natureza_da_configuracao.detalhamento_optativo == gerador.natureza_da_receita.detalhamento_optativo
				nivel_opcional_1_de_acordo = natureza_da_configuracao.nivel_opcional_1 == "00" || natureza_da_configuracao.nivel_opcional_1 == gerador.natureza_da_receita.nivel_opcional_1
				nivel_opcional_2_de_acordo = natureza_da_configuracao.nivel_opcional_2 == "00" || natureza_da_configuracao.nivel_opcional_2 == gerador.natureza_da_receita.nivel_opcional_2
				nivel_opcional_3_de_acordo = natureza_da_configuracao.nivel_opcional_3 == "00" || natureza_da_configuracao.nivel_opcional_3 == gerador.natureza_da_receita.nivel_opcional_3

				natureza_de_acordo = categoria_economica_de_acordo && origem_de_acordo && especie_de_acordo &&
				rubrica_de_acordo && alinea_de_acordo && subalinea_de_acordo && detalhamento_optativo_de_acordo &&
				nivel_opcional_1_de_acordo && nivel_opcional_2_de_acordo && nivel_opcional_3_de_acordo

				return true if natureza_de_acordo
			end
		end

		false
	end


	def texto_de_invalidez_formatado
		texto = ""
		configuracao_do_evento_contabil = evento_contabil.configuracao_do_evento_contabil

		texto << "Evento é filtrado pela modalidade #{configuracao_do_evento_contabil.modalidade_do_empenho} e seu gerador é #{gerador.modalidade_do_empenho_por_model.map{ |me| Contabilidade::ConfiguracaoDoEventoContabil.modalidades_do_empenho.index(me)}.join(', ')} \r\n" unless modalidade_do_empenho_de_acordo_com_o_gerador?
		texto << "Evento é filtrado pelo tipo de pessoa #{configuracao_do_evento_contabil.tipo_de_pessoa} e seu gerador é #{ gerador.try(:tipos_de_pessoa_por_model).map{ |tp| Contabilidade::ConfiguracaoDoEventoContabil.tipo_de_pessoas.index(tp) }.join(', ')} \r\n" unless tipo_de_pessoa_de_acordo_com_o_gerador?
		texto << "Evento é filtrado pelo uso do bem #{configuracao_do_evento_contabil.uso_do_bem} e seu gerador é #{ gerador.uso_do_bem_por_model} \r\n" unless uso_do_bem_de_acordo_com_o_gerador?
		texto << "Evento é filtrado pelo tipo de obra #{configuracao_do_evento_contabil.tipo_de_obra} e seu gerador é #{ gerador.tipo_de_obra_por_model} \r\n" unless tipo_de_obra_de_acordo_com_o_gerador?
		texto << "Evento é filtrado pela conta pcasp da conta bancária #{configuracao_do_evento_contabil.conta_pcasp_da_conta_bancaria.try(:codigo_formatado_e_nome).to_s} e seu gerador é #{ gerador.try(:contas_pcasp_das_contas_bancarias_por_model).try(:map, &:codigo_formatado_e_nome).try(:join, ', ') } \r\n" unless conta_pcasp_da_conta_bancaria_de_acordo_com_o_gerador?
		texto << "Evento é filtrado pela origem da retenção #{configuracao_do_evento_contabil.origem_da_retencao} e seu gerador é #{ gerador.try(:origem_da_retencao_por_model) } \r\n" unless origem_da_retencao_de_acordo_com_o_gerador?
		texto << "Evento é filtrado pelo tipo de crédito #{configuracao_do_evento_contabil.tipo_de_credito} e seu gerador é #{ gerador.try(:tipo_de_credito_por_model) } \r\n" unless tipo_de_credito_de_acordo_com_o_gerador?
		texto << "Evento é filtrado pela origem de recurso #{configuracao_do_evento_contabil.origem_do_recurso} e seu gerador é #{ gerador.try(:origem_do_recurso_por_model) } \r\n" unless origem_do_recurso_de_acordo_com_o_gerador?
		texto << "Evento é filtrado pela tipo de resto a pagar #{configuracao_do_evento_contabil.tipo_de_resto_a_pagar} e seu gerador é #{ gerador.try(:tipo_de_resto_a_pagar_por_model) } \r\n" unless tipo_de_resto_a_pagar_de_acordo_com_o_gerador?
		texto << "Evento é filtrado pela Cancelamento por falta de Disponibilidade de Caixa #{configuracao_do_evento_contabil.cancelamento_por_falta_de_disponibilidade_de_caixa} e seu gerador é #{ gerador.cancelamento_por_falta_de_disponibilidade_de_caixa_por_model } \r\n" unless cancelamento_por_falta_de_disponibilidade_de_caixa_de_acordo_com_o_gerador?
		texto << "Evento é filtrado pelo Empenho Complementar #{configuracao_do_evento_contabil.empenho_complementar} e seu gerador é #{ gerador.try(:empenho_complementar_por_model) } \r\n" unless empenho_complementar_de_acordo_com_o_gerador?
		texto << "Evento é filtrado pelo Resto a Pagar #{configuracao_do_evento_contabil.resto_a_pagar} e seu gerador é #{ gerador.try(:resto_a_pagar_processado_por_model) } \r\n" unless resto_a_pagar_de_acordo_com_o_gerador?
		texto << "Evento é filtrado pelo Processado #{configuracao_do_evento_contabil.processado} e seu gerador é #{ gerador.try(:processado_por_model) } \r\n" unless processado_de_acordo_com_o_gerador?
		texto << "Evento é filtrado pelo Receita de Dedução #{configuracao_do_evento_contabil.receita_de_deducao} e seu gerador é #{ gerador.try(:receita_de_deducao_por_model) } \r\n" unless receita_de_deducao_de_acordo_com_o_gerador?
		texto << "Evento é filtrado pelo Bem lançado #{configuracao_do_evento_contabil.bem_lancado} e seu gerador é #{ gerador.try(:bem_lancado_por_model) } \r\n" unless bem_lancado_de_acordo_com_o_gerador?
		texto << "Evento é filtrado pelo Obra Tombada #{configuracao_do_evento_contabil.obra_tombada} e seu gerador é #{ gerador.try(:obra_tombada) } \r\n" unless obra_tombada_de_acordo_com_o_gerador?
		texto << "Evento é filtrado pelo Veio de uma ordem #{configuracao_do_evento_contabil.veio_de_uma_ordem} e seu gerador é #{ gerador.try(:veio_de_uma_ordem) } \r\n" unless veio_de_uma_ordem_de_acordo_com_o_gerador?
		texto << "Evento é filtrado pelo Extra-Orçamentário #{configuracao_do_evento_contabil.extraorcamentario} e seu gerador é #{ gerador.try(:extraorcamentario) } \r\n" unless extraorcamentario_de_acordo_com_o_gerador?
		texto << "Evento é filtrado pelo Originado de um Evento Manual #{configuracao_do_evento_contabil.originado_de_um_evento_manual} e seu gerador é #{ gerador.try(:originado_de_um_evento_manual) } \r\n" unless originado_de_um_evento_manual_de_acordo_com_o_gerador?
		texto << "Evento é filtrado pelas Natureza(s) #{configuracao_do_evento_contabil.naturezas_da_receita_da_configuracao_contabil.map(&:codigo_de_competencia).join(", ")} e seu gerador é #{ gerador.natureza_da_receita.classificacao.try(:formatar) } \r\n" unless natureza_da_receita_de_acordo_com_o_gerador?
		# texto << "Evento é filtrado pelo Com Fonte de Recursos #{configuracao_do_evento_contabil.com_fonte_de_recursos} e seu gerador é #{ gerador.com_fonte_de_recursos_por_model } \r\n" unless com_fonte_de_recursos_de_acordo_com_o_gerador?
		
		texto
	end
	
	def mes_bloqueado?
		orcamento = Orcamento.find_by(exercicio: self.data_de_lancamento.year)
		balancete_no_mes = Contabilidade::BalanceteDeVerificacao.find_by(mes_de_referencia: self.data_de_lancamento.month, orcamento_id: orcamento.id)
		mes = Contabilidade::BloqueioMensalDoPcasp.find_by(mes_referencia: self.data_de_lancamento.month, orcamento_id: orcamento.id)
		return balancete_no_mes.present? || mes.bloqueado?
	end
	
	def movimento_associado_a_empenho?
		return Contabilidade::Empenho.where(movimentacao_do_plano_de_contas_id: self.id).any? || Contabilidade::Empenho.where(movimentacao_do_plano_de_contas_id: self.movimentacao_par_id).any?
	end

	def subconta_por_tipo_de_movimento
		case self.gerador_type
		when 'Contabilidade::Pagamento'
			return self&.gerador&.empenho&.movimentacao_do_plano_de_contas&.sub_conta_pcasp
		else
			return nil
		end
	end

	private
	def movimenta_saldo_da_conta
		saldo = (self.debito? ? self.conta.saldo.to_f - valor.to_f : self.conta.saldo.to_f + valor.to_f)

		if ( eh_transferencia_de_resto_a_pagar == false ) || ( eh_transferencia_de_resto_a_pagar && ( self.credito? || ( self.debito? && self.conta_por_evento_contabil.conta.conta_de_registro_de_transferencia? ) ) )
			atualiza_saldo_da_conta(self.conta, saldo)
		end
	end

	def define_atributos
		self.evento_contabil_id = evento_contabil.id
		self.grupo_de_evento_id = evento_contabil.grupo_de_evento_contabil_id
	end

	def mudou_de_evento?
		return false if lancamento_manual.nil? || evento_contabil_id.nil?

		if persisted? && conta_por_evento_contabil.present?
			conta_por_evento_contabil.evento_contabil_id != evento_contabil_id
		else
			conta_por_evento_contabil.nil?
		end
	end

	def deleta_movimentacao_par
		movimentacao_par.destroy if movimentacao_par.present?
	end

	def atribui_codigo
		ultima_movimentacao = Contabilidade::MovimentacaoDoPlanoDeContas.last
		self.codigo_movimentacao = ultima_movimentacao.present? ? (Contabilidade::MovimentacaoDoPlanoDeContas.last.id + 1).to_s : 1.to_s
	end

	def cria_e_ou_atribui_sub_conta_pcasp_almoxarifado
		sub_conta_pcasp_almoxarifado = Contabilidade::SubContaPcasp.where(centro_de_custo_id: self.centro_de_custo_id).first rescue nil

		unless sub_conta_pcasp_almoxarifado.present?
			sub_conta_pcasp_almoxarifado = Contabilidade::SubContaPcasp.create(
				centro_de_custo_id: self.centro_de_custo_id,
				topico_da_conta: 'almoxarifado'
			)
		end

		self.sub_conta_pcasp_id = sub_conta_pcasp_almoxarifado.id
	end

	def conta_antiga
		conta_por_evento_contabil_antiga.conta
	end

	def conta_par_antiga
		conta_por_evento_contabil_antiga.conta_par
	end

	def conta_por_evento_contabil_antiga
		Contabilidade::ContaPorEventoContabil.find_by(id: conta_por_evento_contabil_id_was)
	end

	def desfaz_movimentacao_nas_contas
		conta_antiga.update_column('saldo', conta_antiga.saldo + valor_was)
		conta_par_antiga.update_column('saldo', conta_par_antiga.saldo - valor_was)
	end

	def desfaz_alteracoes_nos_saldos_das_diarias
		saldo_do_dia = Contabilidade::SaldoDiarioDaConta.find_by(conta_id: conta_antiga.id, data_do_saldo: self.data_de_lancamento)
		saldo_do_dia_conta_par = Contabilidade::SaldoDiarioDaConta.find_by(conta_id: conta_par_antiga.id, data_do_saldo: self.data_de_lancamento)

		saldo_do_dia.update_column('saldo', saldo_do_dia.saldo + valor_was) if saldo_do_dia.present?
		saldo_do_dia_conta_par.update_column('saldo', saldo_do_dia_conta_par.saldo - valor_was) if saldo_do_dia_conta_par.present?
	end

	def eh_transferencia_de_resto_a_pagar
		acao_transferencia_restos_a_pagar = 32
		self.evento_contabil.evento_de_transferencia? && self.evento_contabil.registros_diversos? && self.evento_contabil.acao_do_sistema.codigo == acao_transferencia_restos_a_pagar
	end

	def atualiza_saldo_diario_da_conta
		saldo_do_dia = Contabilidade::SaldoDiarioDaConta.find_by( conta_id: self.conta.id, data_do_saldo: self.data_de_lancamento)
		valor_com_sinal = self.debito? ? - valor : valor
		if saldo_do_dia.present?
			saldo_do_dia.update(saldo: saldo_do_dia.saldo.to_f + valor_com_sinal)
		else
			Contabilidade::SaldoDiarioDaConta.create!( conta_id: self.conta.id, data_do_saldo: self.data_de_lancamento, saldo: valor_com_sinal)
		end
	end

	def desfaz_movimentacao_no_saldo_da_conta
		saldo = (self.credito? ? self.conta.saldo.to_f - valor.to_f : self.conta.saldo.to_f + valor.to_f)
		self.conta.update_column("saldo", saldo)
		self.conta.reload
	end

	def desfaz_alteracao_no_saldo_diario_da_conta
		saldo_do_dia = Contabilidade::SaldoDiarioDaConta.find_by( conta_id: self.conta.id, data_do_saldo: self.data_de_lancamento)
		if saldo_do_dia.present?
			saldo = (self.credito? ? saldo_do_dia.saldo.to_f - valor.to_f : saldo_do_dia.saldo.to_f + valor.to_f)
			saldo_do_dia.update(saldo: saldo)
		else
			saldo = self.debito? ? self.valor : - self.valor
			Contabilidade::SaldoDiarioDaConta.create!( conta_id: self.conta.id, data_do_saldo: self.data_de_lancamento, saldo: saldo)
		end
	end

	def atualiza_saldo_da_conta conta, saldo
		if Configuracao.last.present? && Configuracao.last.permite_saldo_das_contas_do_plano_de_contas_vire
			conta.update_column('saldo', saldo)
			conta.reload
		else
			if conta.update(saldo: saldo)
				conta.reload
			else
				errors.add(:base, mensagem_de_erro_para_update_de_conta_invalido)
			end
		end
	end

	def mensagem_de_erro_para_update_de_conta_invalido

		natureza_do_saldo_virada = self.conta.devedor? ? 'credor' : 'devedor'
		erro = {
			conta: self.conta.codigo_formatado,
			tipo_de_lancamento: self.tipo_de_lancamento,
			natureza_do_saldo: self.conta.natureza_do_saldo,
			natureza_do_saldo_virada: natureza_do_saldo_virada,
			saldo: self.conta.saldo
		}
		return erro
	end

	def conta_deve_possuir_sub_conta
		if (precatorio? || divida_ativa? || almoxarifado? || provisoes? || imobilizado?) && codigo_da_subconta.present?
			subcontas = conta_por_evento_contabil.conta.contas_filhas.where(detalhamento_extra: codigo_da_subconta) rescue []
	
			errors.add(:evento_contabil_id, "Deve ser criado a subconta com o número #{codigo_da_subconta}") if subcontas.empty?
		end
	end

	def valida_se_ja_houve_envio_do_sim
		errors.add(:sim, 'O SIM do mês já foi enviado') if existe_lote_do_sim? && skip_validacao_sim == false
	end

	def existe_lote_do_sim?
		ultima_data = data_de_lancamento	

		if ultima_data.present?
			lote_sim = Tcm::Lote.find_by(
				orcamento_id: Orcamento.where(exercicio: ultima_data.year).last,
				tipo: [Tcm::Lote.tipos[:todos], Tcm::Lote.tipos[:contabilidade]],
				mes_de_referencia: ultima_data.month,
				situacao: [Tcm::Lote.situacoes[:gerado], Tcm::Lote.situacoes[:finalizado]]
			)

			return lote_sim.present?
		end

		return false
	end

	def valida_ics_debito
		if self.conta.present?
			# ic_fp
			if self.conta.informacao_complementar_possui_atributo_financeiro?
				errors.add(:ic_fp, 'O atributo financeiro deve ser preenchido') if self.ic_fp.blank?
			else
				errors.add(:ic_fp, 'O atributo financeiro não deve ser preenchido') if self.ic_fp.present?
			end

			# fonte_de_recursos_id
			if self.conta.informacao_complementar_possui_fonte_de_recursos?
				errors.add(:fonte_de_recursos_id, 'A fonte de recursos deve ser preenchida') if self.fonte_de_recursos_id.blank?
			else
				errors.add(:fonte_de_recursos_id, 'A fonte de recursos não deve ser preenchida') if self.fonte_de_recursos_id.present?
			end

			# ic_nr
			if self.conta.informacao_complementar_possui_natureza_da_receita?
				errors.add(:ic_nr, 'A natureza da receita deve ser preenchida') if self.ic_nr.blank?
			else
				errors.add(:ic_nr, 'A natureza da receita não deve ser preenchida') if self.ic_nr.present?
			end

			# ic_nd
			if self.conta.informacao_complementar_possui_natureza_da_despesa?
				errors.add(:ic_nd, 'A natureza da despesa deve ser preenchida') if self.ic_nd.blank?
			else
				errors.add(:ic_nd, 'A natureza da despesa não deve ser preenchida') if self.ic_nd.present?
			end

			# ic_fs
			if self.conta.informacao_complementar_possui_funcao_e_subfuncao?
				errors.add(:ic_fs, 'A funcao e subfuncao deve ser preenchida') if self.ic_fs.blank?
			else
				errors.add(:ic_fs, 'A funcao e subfuncao não deve ser preenchida') if self.ic_fs.present?
			end
		end
	end

	def valida_ics_credito
		if self.conta_par.present?
			# ic_fp_credito
			if self.conta_par.informacao_complementar_possui_atributo_financeiro?
				errors.add(:ic_fp_credito, 'O atributo financeiro deve ser preenchido') if self.ic_fp_credito.blank?
			else
				errors.add(:ic_fp_credito, 'O atributo financeiro não deve ser preenchido') if self.ic_fp_credito.present?
			end

			# fonte_de_recursos_credito_id
			if self.conta_par.informacao_complementar_possui_fonte_de_recursos?
				errors.add(:fonte_de_recursos_credito_id, 'A fonte de recursos deve ser preenchida') if self.fonte_de_recursos_credito_id.blank?
			else
				errors.add(:fonte_de_recursos_credito_id, 'A fonte de recursos não deve ser preenchida') if self.fonte_de_recursos_credito_id.present?
			end

			# ic_nr_credito
			if self.conta_par.informacao_complementar_possui_natureza_da_receita?
				errors.add(:ic_nr_credito, 'A natureza da receita deve ser preenchida') if self.ic_nr_credito.blank?
			else
				errors.add(:ic_nr_credito, 'A natureza da receita não deve ser preenchida') if self.ic_nr_credito.present?
			end

			# ic_nd_credito
			if self.conta_par.informacao_complementar_possui_natureza_da_despesa?
				errors.add(:ic_nd_credito, 'A natureza da despesa deve ser preenchida') if self.ic_nd_credito.blank?
			else
				errors.add(:ic_nd_credito, 'A natureza da despesa não deve ser preenchida') if self.ic_nd_credito.present?
			end

			# ic_fs_credito
			if self.conta_par.informacao_complementar_possui_funcao_e_subfuncao?
				errors.add(:ic_fs_credito, 'A funcao e subfuncao deve ser preenchida') if self.ic_fs_credito.blank?
			else
				errors.add(:ic_fs_credito, 'A funcao e subfuncao não deve ser preenchida') if self.ic_fs_credito.present?
			end
		end
	end
	

	def valida_se_ja_houve_geracao_do_balancete
		errors.add(:sim, 'O Balancete de Verificação do mês já foi gerado.') if existe_balancete_do_sim? && skip_validacao_sim == false
	end

	def valida_se_mes_esta_bloqueado
		errors.add(:data_de_lancamento, 'O mês está bloqueado.') if mes_bloqueado?
	end

	def valida_se_existe_empenho_associado_ao_movimento
		errors.add(:id, 'O movimento está associado a um empenho e não pode ser excluido') if movimento_associado_a_empenho?
	end

	def existe_balancete_do_sim?
		ultima_data = data_de_lancamento

		if ultima_data.present?
			lote_sim = Contabilidade::BalanceteDeVerificacao.find_by(
				orcamento_id: Orcamento.where(exercicio: ultima_data.year).last,
				mes_de_referencia: ultima_data.month
			)

			return lote_sim.present?
		end

		return false
	end


	def atribui_valor
		self.valor = gerador.valor_movimentado
	end

	def atribui_data_de_lancamento
		self.data_de_lancamento = gerador.data_movimentada
	end

	def atribui_conta_bancaria
		conta_bancaria_a_utilizar = nil
		case self.gerador_type
			when "Contabilidade::TransferenciaFinanceira"
				if conta_por_evento_contabil.debito? 
					conta_bancaria_a_utilizar = self.gerador&.conta_bancaria_destino&.conta_bancaria_id rescue nil
				else
					conta_bancaria_a_utilizar = self.gerador&.conta_bancaria_origem&.conta_bancaria_id rescue nil
				end
			when "Contabilidade::Pagamento"
				conta_bancaria_a_utilizar = self.gerador&.contas_bancarias_por_pagamento&.first&.conta_bancaria_id
			when "Contabilidade::EstornoDePagamento"
				conta_bancaria_a_utilizar = self.gerador&.pagamento&.contas_bancarias_por_pagamento&.first&.conta_bancaria_id
			when "Contabilidade::DespesaExtraOrcamentaria"
				conta_bancaria_a_utilizar = self.gerador&.conta_bancaria_por_unidade_orcamentaria&.conta_bancaria&.id
			when "Contabilidade::EstornoDeDespesaExtraOrcamentaria"
				conta_bancaria_a_utilizar = self.gerador&.despesa_extra_orcamentaria&.conta_bancaria_por_unidade_orcamentaria&.conta_bancaria&.id
			when "Contabilidade::AnulacaoDoTalaoDeReceita"
				conta_bancaria_a_utilizar = self.gerador&.talao_de_receita&.conta_bancaria&.id
			when "Contabilidade::TalaoDeReceita"
				if self.gerador&.retencao.present? && self.gerador&.conta_bancaria.nil?
					conta_bancaria_a_utilizar = self.gerador&.pagamento&.contas_bancarias_por_pagamento&.first&.conta_bancaria_id
				else
					conta_bancaria_a_utilizar = self.gerador&.conta_bancaria&.id
				end
			when "Contabilidade::AnulacaoDoTalaoDeReceita"
				if self.gerador&.talao_de_receita&.retencao.present? && self.gerador&.talao_de_receita&.conta_bancaria.nil?
					conta_bancaria_a_utilizar = self.gerador&.talao_de_receita&.pagamento&.contas_bancarias_por_pagamento&.first&.conta_bancaria_id
				else
					conta_bancaria_a_utilizar = self.gerador&.talao_de_receita&.conta_bancaria&.id
				end
			else
				conta_bancaria_a_utilizar = (self.gerador.conta_bancaria.try(:id) || self.gerador.conta_bancaria_por_classe.try(:id)) rescue nil
		end
		self.conta_bancaria_id = conta_bancaria_a_utilizar
	end

	def preenche_campos_ics
		self.ic_po = poder_ou_orgao_formatado
		self.ic_fp = codigo_superavit_financeiro if self.conta.informacao_complementar_possui_atributo_financeiro? && !self.ic_fp.present?
		self.ic_dc = codigo_divida_consolidada if ((self.conta.informacao_complementar_possui_divida_consolidada? && !self.ic_dc.present?) || self&.sub_conta_pcasp&.divida_consolidada?)
		self.ic_fr = codigo_fonte_de_recursos_formatado if self.conta.informacao_complementar_possui_fonte_de_recursos? && !self.ic_fr.present?
		self.ic_co = codigo_acompanhamento_formatado if self.conta.informacao_complementar_possui_complemento_de_fonte? && (!self.ic_co.present? || ic_co == '0000')
		self.ic_nr = codigo_natureza_da_receita_formatada if self.conta.informacao_complementar_possui_natureza_da_receita? && !self.ic_nr.present?
		self.ic_nd = codigo_natureza_da_despesa_formatada if self.conta.informacao_complementar_possui_natureza_da_despesa? && !self.ic_nd.present?
		self.ic_fs = codigo_funcao_e_subfuncao if self.conta.informacao_complementar_possui_funcao_e_subfuncao? && !self.ic_fs.present?
		self.ic_ai = codigo_ano_de_inscricao_resto_a_pagar if self.conta.informacao_complementar_possui_ano_de_restos_a_pagar? && !self.ic_ai.present?
	end

	def atribui_conta_por_evento_contabil_precatorio
		evento_contabil = Contabilidade::EventoContabil.find_by(id: evento_contabil_id)
		conta_filha_id = evento_contabil.contas_por_eventos_contabeis.joins(:conta).find_by(contabilidade_contas: {detalhamento_extra: numero_do_processo_judicial}).try(:id)

		if conta_filha_id.present?
			self.conta_por_evento_contabil_id = conta_filha_id
		else
			conta_pai = evento_contabil.contas_por_eventos_contabeis.debito.where(conta_principal: true).first
			self.conta_por_evento_contabil_id = Contabilidade::ContaPorEventoContabil.create({
				conta_id: conta_pai.conta.contas_filhas.find_by(detalhamento_extra: numero_do_processo_judicial).try(:id),
				evento_contabil_id: evento_contabil_id,
				tipo_de_lancamento: 'debito',
				conta_par_id: conta_pai.conta_par_id,
				ordem_de_lancamento: 1,
				conta_principal: false
			}).try(:id)
		end
	end

	def verifica_se_a_subconta_esta_inativa
		if sub_conta_pcasp.present? && sub_conta_pcasp.inativo?
			errors.add(:sub_conta_pcasp_id, "A conta PCASP está inativa e não pode receber novos movimentos")
		end
	end
end
