class Contabilidade::SolicitacaoDeAlteracaoOrcamentaria < ApplicationRecord
	has_paper_trail
	include IncrementadorDeCodigoConcern
	include GeradorDeEventosContabeis
	include AASM
	include TradutorConcern
	include MensagemConcern

	attr_default  :status, :solicitado
	attr_default  :criado_na_gestao_do_orcamento, :false
	attr_default  :skip_validate_valida_valor_dotacoes_origem, false

	attr_accessor :logado_na_contabilidade, :orcamento_da_despesa_id, :logado_na_alteracao_orcamentaria, :valor_do_empenho
	attr_accessor :logado_no_administrativo
	attr_accessor :dotacoes_destino_hidden, :dotacoes_origem_hidden
	attr_accessor :vem_do_decreto
	attr_accessor :skip_validate_valida_valor_dotacoes_origem

	belongs_to :projeto, class_name: 'Licitacao::Projeto'
	belongs_to :decreto
	belongs_to :empenho
	belongs_to :unidade_orcamentaria, class_name: 'Loa::UnidadeOrcamentaria'
	belongs_to :programa_de_governo_da_solicitacao, class_name: 'Loa::ProgramaDeGoverno'
	belongs_to :fonte_de_recursos, class_name: 'Base::FonteDeRecursos'
	belongs_to :orcamento, class_name: 'Orcamento'
	belongs_to :operacao_de_credito, class_name: 'Obra::OperacaoDeCredito'

	has_many :dotacoes_origem, class_name: 'Contabilidade::DotacaoOrigem', dependent: :destroy
	has_many :dotacoes_destino, class_name: 'Contabilidade::DotacaoDestino', dependent: :destroy
	has_many :orcamentos_da_despesa_destino, through: :dotacoes_destino, source: :orcamento_da_despesa, class_name: 'Loa::OrcamentoDaDespesa'
	has_many :orcamentos_da_despesa_origem, through: :dotacoes_origem, source: :orcamento_da_despesa, class_name: 'Loa::OrcamentoDaDespesa'
	has_many :subacoes_da_solicitacao, dependent: :destroy
	has_many :elementos_por_subacao_da_solicitacao, through: :subacoes_da_solicitacao
	has_many :fontes_por_elemento_da_subacao_da_solicitacao, through: :elementos_por_subacao_da_solicitacao
	has_many :acao, class_name: 'Loa::Acao'
	has_many :programa_de_governo, class_name: 'Loa::ProgramaDeGoverno'

	validates_presence_of :origem_do_recurso
	validates_presence_of :decreto_id, if: Proc.new { self.logado_na_alteracao_orcamentaria.present? }
	validates_presence_of :tipo_de_credito, if: Proc.new { self.logado_na_alteracao_orcamentaria.present? || self.logado_no_administrativo.present? }
	validates_presence_of :programa_de_governo_da_solicitacao_id, if: Proc.new { credito_especial_ou_extraordinario? && self.nova_acao? }
	validates_presence_of :operacao_de_credito_id, if: Proc.new { self.operacao_de_credito? }

	validates_absence_of :novo_programa, if: Proc.new { self.credito_suplementar? || self.nova_acao? }, message: "Tipo de crédito deve ser especial ou extraordinário, você só pode marcar uma das opções"
	validates_absence_of :nova_acao, if: Proc.new { self.credito_suplementar? || self.novo_programa? }, message: "Tipo de crédito deve ser especial ou extraordinário, você só pode marcar uma das opções"

	accepts_nested_attributes_for :dotacoes_origem, reject_if: :all_blank, allow_destroy: true
	accepts_nested_attributes_for :dotacoes_destino, reject_if: :all_blank, allow_destroy: true
	accepts_nested_attributes_for :subacoes_da_solicitacao, reject_if: :all_blank, allow_destroy: true

	validates_associated :dotacoes_origem
	validates_associated :dotacoes_destino
	validates_associated :subacoes_da_solicitacao

	validates :dotacoes_origem, uniq_nested_attributes: { atributo: :dotacao_id, mensagem: "Dotação deve ser única dentro de uma solicitação"}
	validates :dotacoes_destino, uniq_nested_attributes: { atributo: :dotacao_id, mensagem: "Dotação deve ser única dentro de uma solicitação"}
	validates :subacoes_da_solicitacao, uniq_nested_attributes: { atributo: :subacao_id, mensagem: "Ação deve ser única dentro de uma solicitação"}

	validate :valida_decreto_transposicao, if: Proc.new { dotacoes_origem.any? && dotacoes_destino.any? && decreto.present? && decreto.transposicao? }
	validate :valida_decreto_transferencia, if: Proc.new { dotacoes_origem.any? && dotacoes_destino.any? && decreto.present? && decreto.transferencias? }
	validate :valida_decreto_comum, if: Proc.new { dotacoes_origem.any? && dotacoes_destino.any? && decreto.present? && decreto.comum? }
	validate :valida_valor_dotacoes_origem, if: Proc.new { dotacoes_origem.any? && self.skip_validate_valida_valor_dotacoes_origem == false }
	validate :valida_fontes_das_dotacoes, if: Proc.new { dotacoes_destino.any? && dotacoes_origem.any?}
	validate :valida_saldo_para_superavit, if: Proc.new { superavit_financeiro? && (self.dotacoes_destino.any? || self.dotacoes_origem.any?) }
	validate :valida_valor_das_dotacoes, if: Proc.new { !self.credito_de_reducao? && !self.superavit_financeiro? }
	validate :verifica_anulacao_de_dotacao, on: :update, if: Proc.new {self.confirmado? && self.origem_do_recurso_changed?}
	validate :valida_valor_por_operacao_de_credito, if: Proc.new {self.operacao_de_credito? && self.operacao_de_credito_id.present?}
	validate :verifica_saldo_da_operacao_de_credito, if: Proc.new {self.operacao_de_credito? && self.operacao_de_credito_id.present?}
	validate :verifica_tipo_de_credito, if: Proc.new {self.tipo_de_credito_changed? && (self.credito_extraordinario? || self.credito_especial?)}
	# validate :valida_fontes_de_recurso_devem_ser_iguais?, if: Proc.new { dotacoes_destino.any? && dotacoes_origem.any? }
	#validate :fonte_de_recurso_maior_ou_menor, if: Proc.new { dotacoes_destino.any? && dotacoes_origem.any? }
	validate :valor_dotacao_destino_menor_que_zero, if: Proc.new { dotacoes_destino.any? }
	validate :data_do_empenho_deve_estar_dentro_da_data_do_decreto, if: Proc.new { self.empenho_id.present? && self.decreto_id.present? }
	validate :data_do_projeto_deve_estar_dentro_da_data_do_decreto, if: Proc.new { self.projeto_id.present? && self.decreto_id.present? }
	validate :valida_se_ja_houve_envio_do_sim

	after_save :atribui_codigo_disponivel

	after_save :remover_dotacoes_de_origem, if: Proc.new { self.superavit_financeiro? && self.dotacoes_origem.any? }
	after_create :adiciona_dotacoes_do_projeto_na_dotacao_destino, if: Proc.new { self.logado_na_contabilidade.blank? && self.projeto_id.present? }
	after_create :adiciona_dotacao_do_empenho_na_dotacao_destino, if: Proc.new { (self.empenho.present? && self.empenho.orcamento_da_despesa_id.present?) || self.orcamento_da_despesa_id.present? }
	after_save :lancar_movimento_orcamentario, if: Proc.new { confirmado? }
	after_destroy :apagar_movimento_orcamentario

	enum origem_do_recurso: {
		anulacao_de_dotacao: 0,
		outros: 1,
		execesso_de_arrecadacao: 2,
		superavit_financeiro: 3,
		revigoramento_de_credito: 4,
		operacao_de_credito: 5,
		revigoramento_de_credito_especial: 6,
		revigoramento_de_credito_extraordinario: 7,
		reserva_de_contigencia: 8
	}

	enum tipo_de_credito: {
		credito_suplementar: 0,
		credito_especial: 1,
		credito_extraordinario: 2,
		credito_de_reducao: 3
	}

	enum status: {
		solicitado: 0,
		enviado_ao_planejamento: 1,
		indeferido: 2,
		pre_confirmado: 3,
		confirmado: 4
	}

	# EVENTOS
	aasm column: :status, enum: true, whiny_transitions: false do
		state :solicitado, :initial => true
		state :enviado_ao_planejamento
		state :indeferido
		state :pre_confirmado
		state :confirmado

		event :enviar_para_contabilidade do
			transitions from: :solicitado, to: :enviado_ao_planejamento do
				guard do
					possui_dotacoes_de_origem? || possui_dotacoes_de_destino?
				end

				after do
					cria_mensagem_enviado_ao_planejamento
				end
			end
		end

		event :indeferir do
			transitions from: :enviado_ao_planejamento, to: :indeferido
		end

		event :confirmar do
			transitions from: :enviado_ao_planejamento, to: :confirmado do
				guard do
					if self.anulacao_de_dotacao?
						((possui_dotacoes_de_origem? || possui_dotacoes_de_destino?) && decreto.present? && !valores_das_dotacoes_sao_diferentes?) && self.valor_das_dotacoes_iguais_ao_cadastro? && possui_acao_ou_programa?
					else
						(possui_dotacoes_de_destino? && decreto.present? && valor_das_dotacoes_iguais_ao_cadastro?) && possui_acao_ou_programa?
					end
				end

				after do
					self.skip_validate_valida_valor_dotacoes_origem = true
					lancar_movimento_orcamentario
					self.skip_callback = false
					self.gerar_todos_os_movimentos(:data_do_talao, orcamento)
				end
			end

			transitions from: :solicitado, to: :confirmado do
				guard do
					if !self.credito_de_reducao?
						if self.anulacao_de_dotacao?
							if credito_especial_ou_extraordinario?
								(possui_dotacoes_de_origem? || possui_dotacoes_de_destino?) && !valores_das_dotacoes_sao_diferentes? && decreto.present? && ((!self.novo_programa? && !self.nova_acao? && possui_orcamentos_vinculados?) ||
									(self.novo_programa? && programa_de_governo.present?) || (self.nova_acao? && acao.present?)) && self.dotacao_origem_possui_saldo_suciente_pra_confirmar?
							else
								(possui_dotacoes_de_origem? || possui_dotacoes_de_destino?) && !valores_das_dotacoes_sao_diferentes? && decreto.present? && self.dotacao_origem_possui_saldo_suciente_pra_confirmar?
							end
						else
							if credito_especial_ou_extraordinario?
								possui_dotacoes_de_destino? && decreto.present? && !valores_das_dotacoes_sao_diferentes? &&
									((!self.novo_programa? && !self.nova_acao? && possui_orcamentos_vinculados?) || (self.novo_programa? && programa_de_governo.present?) || (self.nova_acao? && acao.present?))
							else
								possui_dotacoes_de_destino? && decreto.present?
							end
						end
					else
						(possui_dotacoes_de_origem? || possui_dotacoes_de_destino?) && decreto.present?
					end
				end

				after do
					self.skip_validate_valida_valor_dotacoes_origem = true
					lancar_movimento_orcamentario
					self.skip_callback = false
					self.gerar_todos_os_movimentos(:data_do_talao, orcamento)
				end
			end
			transitions from: :pre_confirmado, to: :confirmado do
				guard do
					if !self.credito_de_reducao?
						if self.anulacao_de_dotacao?
							if credito_especial_ou_extraordinario?
								(possui_dotacoes_de_origem? || possui_dotacoes_de_destino?) && !valores_das_dotacoes_sao_diferentes? && self.valor_das_dotacoes_iguais_ao_cadastro? && decreto.present? &&
									((!self.novo_programa? && !self.nova_acao? && possui_orcamentos_vinculados?) || (self.novo_programa? && programa_de_governo.present?) || (self.nova_acao? && acao.present?))
							else
								(possui_dotacoes_de_origem? || possui_dotacoes_de_destino?) && !valores_das_dotacoes_sao_diferentes? && self.valor_das_dotacoes_iguais_ao_cadastro? && decreto.present?
							end
						else
							if credito_especial_ou_extraordinario?
								possui_dotacoes_de_destino? && !valores_das_dotacoes_sao_diferentes? && self.valor_das_dotacoes_iguais_ao_cadastro? && decreto.present? &&
									((!self.novo_programa? && !self.nova_acao? && possui_orcamentos_vinculados?) || (self.novo_programa? && programa_de_governo.present?) || (self.nova_acao? && acao.present?))
							else
								possui_dotacoes_de_destino? && decreto.present? && valor_das_dotacoes_iguais_ao_cadastro?
							end
						end
					else
						(possui_dotacoes_de_origem? || possui_dotacoes_de_destino?) && decreto.present?
					end
				end

				after do
					self.skip_validate_valida_valor_dotacoes_origem = true
					lancar_movimento_orcamentario
					atualiza_valor_das_fontes if credito_especial_ou_extraordinario?
					self.skip_callback = false
					self.gerar_todos_os_movimentos(:data_do_talao, orcamento)
				end
			end
		end

		event :voltar_etapa do
			transitions from: :confirmado, to: :solicitado do
				guard do
					self.skip_validate_valida_valor_dotacoes_origem = true
					self.pode_voltar_etapa?
				end
			end
			after do
				self.apagar_movimento_orcamentario
			end
		end

	end

	def pode_voltar_etapa?
		self.decreto.aberto? && !gerou_orc_da_despesa_que_possui_outros_lancamentos? && self.dotacoes_destino.map{|dot| (dot.orcamento_da_despesa.saldo_da_dotacao_por_data(self.data_da_legislacao).to_d - dot.valor.to_d) >= 0 && (dot.orcamento_da_despesa.saldo.to_d - dot.valor.to_d) >= 0}.all?
	end

	def dotacao_origem_possui_saldo_suciente_pra_confirmar?
		self.dotacoes_origem.first.orcamento_da_despesa.saldo.to_f >= self.dotacoes_origem.first.valor
	end

	def gerou_orc_da_despesa_que_possui_outros_lancamentos?
		return false unless self.possui_orcamentos_vinculados?

		dotacoes = self.fontes_por_elemento_da_subacao_da_solicitacao.map{|fonte| fonte.orcamento_da_despesa_vinculado }.compact
		return dotacoes.any?{|dotacao| dotacao.lancamentos_do_orcamento_da_despesa.where("data_do_lancamento > ?", self.data_da_legislacao).count > 1}
	end

	# VALIDAÇÕES
	def valida_decreto_remanejamento
		if dotacoes_destino.any?{|dotacao| dotacao.orcamento_da_despesa.present?} && dotacoes_origem.any?{|dotacao| dotacao.orcamento_da_despesa.present?}
			orgaos_destino = Loa::OrcamentoDaDespesa.where(id: dotacoes_destino.map{|dotacao| dotacao.orcamento_da_despesa.id}).joins(elemento_de_despesa_por_subacao: [subacao: :unidade_orcamentaria]).pluck(:orgao_id)
			orgaos_origem = Loa::OrcamentoDaDespesa.where(id: dotacoes_origem.map{|dotacao| dotacao.orcamento_da_despesa.id}).joins(elemento_de_despesa_por_subacao: [subacao: :unidade_orcamentaria]).pluck(:orgao_id)

			if orgaos_destino != orgaos_origem
				return true
			end
		end
	end

	def verifica_tipo_de_credito
		if self.dotacoes_origem.present? || self.dotacoes_destino.present?
			errors.add(:tipo_de_credito, "Para esse tipo de crédito a alteração não pode ter dotações cadastradas.")
		end
	end

	def valida_valor_por_operacao_de_credito
		valor_operacao_credito = self.operacao_de_credito.valor_total.to_f
		errors.add(:valor_a_suplementar, "O valor da suplementação deve ser menor ou igual ao da operação de credito escolhida #{valor_total.real_contabil}") if valor_a_suplementar.to_f > valor_operacao_credito.to_f
	end

	def verifica_saldo_da_operacao_de_credito
		saldo_da_operacao_de_credito = self.operacao_de_credito.saldo_para_alteracao_orcamentaria.to_f
		errors.add(:operacao_de_credito_id, "A operação escolhida não possui saldo suficiente") if saldo_da_operacao_de_credito.to_f < 0
	end

	def valida_decreto_comum
		if dotacoes_destino.any?{|dotacao| dotacao.orcamento_da_despesa.present?} && dotacoes_origem.any?{|dotacao| dotacao.orcamento_da_despesa.present?}
			orgaos_destino = Loa::OrcamentoDaDespesa.where(id: dotacoes_destino.map{|dotacao| dotacao.orcamento_da_despesa.id}).joins(elemento_de_despesa_por_subacao: [subacao: :unidade_orcamentaria]).pluck(:orgao_id)
			orgaos_origem = Loa::OrcamentoDaDespesa.where(id: dotacoes_origem.map{|dotacao| dotacao.orcamento_da_despesa.id}).joins(elemento_de_despesa_por_subacao: [subacao: :unidade_orcamentaria]).pluck(:orgao_id)

			programas_destino = Loa::OrcamentoDaDespesa.where(id: dotacoes_destino.map{|dotacao| dotacao.orcamento_da_despesa.id}).joins(elemento_de_despesa_por_subacao: [subacao: :acao]).pluck(:programa_de_governo_id)
			programas_origem = Loa::OrcamentoDaDespesa.where(id: dotacoes_origem.map{|dotacao| dotacao.orcamento_da_despesa.id}).joins(elemento_de_despesa_por_subacao: [subacao: :acao]).pluck(:programa_de_governo_id)

			categorias_destino = Loa::OrcamentoDaDespesa.where(id: dotacoes_destino.map{|dotacao| dotacao.orcamento_da_despesa.id}).joins(elemento_de_despesa_por_subacao: :elemento_de_despesa).pluck(:elemento_de_gasto_id)
			categorias_origem = Loa::OrcamentoDaDespesa.where(id: dotacoes_origem.map{|dotacao| dotacao.orcamento_da_despesa.id}).joins(elemento_de_despesa_por_subacao: :elemento_de_despesa).pluck(:elemento_de_gasto_id)

			if orgaos_destino == orgaos_origem && programas_destino == programas_origem && categorias_destino == categorias_origem
				return true
			end
		end
	end

	def valida_decreto_transferencia
		if dotacoes_destino.any?{|dotacao| dotacao.orcamento_da_despesa.present?} && dotacoes_origem.any?{|dotacao| dotacao.orcamento_da_despesa.present?}
			orgaos_destino = Loa::OrcamentoDaDespesa.where(id: dotacoes_destino.map{|dotacao| dotacao.orcamento_da_despesa.id}).joins(elemento_de_despesa_por_subacao: [subacao: :unidade_orcamentaria]).pluck(:orgao_id)
			orgaos_origem = Loa::OrcamentoDaDespesa.where(id: dotacoes_origem.map{|dotacao| dotacao.orcamento_da_despesa.id}).joins(elemento_de_despesa_por_subacao: [subacao: :unidade_orcamentaria]).pluck(:orgao_id)

			categorias_destino = Loa::OrcamentoDaDespesa.where(id: dotacoes_destino.map{|dotacao| dotacao.orcamento_da_despesa.id}).joins(elemento_de_despesa_por_subacao: :elemento_de_despesa).pluck(:elemento_de_gasto_id)
			categorias_origem = Loa::OrcamentoDaDespesa.where(id: dotacoes_origem.map{|dotacao| dotacao.orcamento_da_despesa.id}).joins(elemento_de_despesa_por_subacao: :elemento_de_despesa).pluck(:elemento_de_gasto_id)

			if orgaos_destino == orgaos_origem && categorias_destino != categorias_origem
				return true
			end
		end
	end

	def valida_decreto_transposicao
		if dotacoes_destino.any?{|dotacao| dotacao.orcamento_da_despesa.present?} && dotacoes_origem.any?{|dotacao| dotacao.orcamento_da_despesa.present?}
			orgaos_destino = Loa::OrcamentoDaDespesa.where(id: dotacoes_destino.map{|dotacao| dotacao.orcamento_da_despesa.id}).joins(elemento_de_despesa_por_subacao: [subacao: :unidade_orcamentaria]).pluck(:orgao_id)
			orgaos_origem = Loa::OrcamentoDaDespesa.where(id: dotacoes_origem.map{|dotacao| dotacao.orcamento_da_despesa.id}).joins(elemento_de_despesa_por_subacao: [subacao: :unidade_orcamentaria]).pluck(:orgao_id)

			if orgaos_destino.uniq == orgaos_origem.uniq
				return true
			end
		end
	end

	def valida_fontes_das_dotacoes
		if (!self.anulacao_de_dotacao? && dotacoes_destino.any?{|dotacao| dotacao.orcamento_da_despesa.present?} && dotacoes_origem.any?{|dotacao| dotacao.orcamento_da_despesa.present?}) && (!dotacoes_origem.all?{|dotacao| dotacao.marked_for_destruction?} && !dotacoes_destino.all?{|dotacao| dotacao.marked_for_destruction?})
			fontes_destino_agrupados = self.dotacoes_destino.group_by{|dotacao| dotacao.orcamento_da_despesa.fonte_de_recursos}

			fontes_destino_agrupados.each do |fonte_destino, dotacoes|
				soma_dotacoes_destino = dotacoes.inject(0){|sum,d| sum + d.valor }
				soma_dotacoes_origem = 0
				self.dotacoes_origem.each do |dotacao_destino|
					if dotacao_destino.orcamento_da_despesa.fonte_de_recursos == fonte_destino
							soma_dotacoes_origem += dotacao_destino.valor
					end
				end
				errors.add(:base, "As reduções e acréscimos com a fonte (#{fonte_destino.codigo_completo}) devem ter o mesmo valor total") if soma_dotacoes_destino != soma_dotacoes_origem
			end
		end
	end

	def valida_valor_das_dotacoes
		soma_dd = dotacoes_destino.reject(&:marked_for_destruction?).sum(&:valor)
		soma_do = dotacoes_origem.reject(&:marked_for_destruction?).sum(&:valor)
		
		if soma_dd.to_d > 0 || soma_do.to_d > 0
			errors.add(:valor_dotacoes, "O valor total das reduções dever ser igual ao valor total dos acréscimos da dotação.") if self.valores_das_dotacoes_sao_diferentes?
		end
	end

	def valida_saldo_para_superavit
		if self.origem_do_recurso_changed?
			valor_do_superavit = self.orcamento.saldo_superavit.to_f
		else
			valor_do_superavit = self.orcamento.saldo_superavit.to_f + self.soma_das_dotacoes_antigas.to_f
		end
		if valor_do_superavit.to_f < self.valor_a_suplementar.to_f
			errors.add(:valor_a_suplementar, "Não Tem Saldo de Superávit Suficiente")
		end
	end

	def verifica_anulacao_de_dotacao
		if self.anulacao_de_dotacao? && !dotacoes_origem.any?
			errors.add(:origem_do_recurso, "Não é possível alterar Origem do Recurso para Anulação de Dotação quando já está confirmado.")
		end
	end

	def valida_valor_dotacoes_origem
		dotacoes_origem.where('valor > 0').each do |dotacao_de_origem|
			if dotacao_de_origem.valor_changed? && dotacao_de_origem.valor.present? && dotacao_de_origem.orcamento_da_despesa
				errors.add(:dotacoes, dotacao_de_origem.orcamento_da_despesa) if dotacao_de_origem.orcamento_da_despesa.saldo.to_d - dotacao_de_origem.valor_was.to_d < dotacao_de_origem.valor.to_d
			end
		end
	end

	# def valida_fontes_de_recurso_devem_ser_iguais?
	# 	fonte_de_recurso_destino = self.dotacoes_destino.map { |dotacao_destino| dotacao_destino.orcamento_da_despesa.fonte_de_recursos.codigo_completo } rescue Array.new
	# 	fonte_de_recursos_origem = self.dotacoes_origem.map { |dotacao_origem| dotacao_origem.orcamento_da_despesa.fonte_de_recursos.codigo_completo } rescue Array.new

	# 	errors.add(:base ,"Na Reduçao pelo menos uma Fonte de Recurso deve ser igual a de Acréscimo.") if (fonte_de_recurso_destino & fonte_de_recursos_origem).empty?
	# end

	# BOOLEANS
	def credito_especial_ou_extraordinario?
		self.credito_especial? || self.credito_extraordinario?
	end

	def possui_acao_ou_programa?
		if credito_especial_ou_extraordinario?
			((!self.novo_programa? && !self.nova_acao? && possui_orcamentos_vinculados?) || (self.novo_programa? && programa_de_governo.present?) || (self.nova_acao? && acao.present?))
		else
			return true
		end
	end

	def mostrar_aba_dotacoes?
		if credito_especial_ou_extraordinario?
			if (self.nova_acao && acao.blank?) || (self.novo_programa && programa_de_governo.blank?) ||
				(!self.nova_acao && !self.novo_programa && !possui_orcamentos_vinculados?)
					return false
			end
		end
		return true
	end

	def valor_das_dotacoes_iguais_ao_cadastro?
		if dotacoes_origem.any? && dotacoes_destino.any?
			soma_dotacoes_origem.to_f == soma_dotacoes_destino.to_f
		else
			true
		end
	end

	def possui_dotacoes_de_origem?
		dotacoes_origem.any?
	end

	def possui_dotacoes_de_destino?
		dotacoes_destino.any?
	end

	def decreto_fechado?
		decreto.present? && decreto.try(:fechado?)
	end

	def possui_orcamentos_vinculados?
		credito_especial_ou_extraordinario? && fontes_por_elemento_da_subacao_da_solicitacao.any?
	end

	def valores_das_dotacoes_sao_diferentes?
		if (self.anulacao_de_dotacao? && self.fonte_de_recursos.nil?) || self.decreto_para_reducao?
			soma_dd = dotacoes_destino.reject(&:marked_for_destruction?).sum(&:valor)
			soma_do = dotacoes_origem.reject(&:marked_for_destruction?).sum(&:valor)

			soma_dd.to_d != soma_do.to_d
		else
			false
		end
	end

	def vem_de_projeto_ou_empenho?
		self.projeto.present? || self.empenho.present?
	end

	def enviado_para_o_sim?
		if self.confirmado?
			dotacoes_origem_enviada_ao_sim? && dotacoes_destino_enviada_ao_sim?
		else
			false
		end
	end

	def decreto_para_acrescimo?
		self.credito_de_reducao? && fonte_de_recursos.present? && decreto.present? &&
			decreto.valor_reajuste_origem_por_fonte(fonte_de_recursos.id).to_f >= decreto.valor_reajuste_destino_por_fonte(fonte_de_recursos.id).to_f
	end

	def decreto_para_reducao?
		self.credito_de_reducao? && fonte_de_recursos.present? && decreto.present? &&
			decreto.valor_reajuste_destino_por_fonte(fonte_de_recursos.id).to_f >= decreto.valor_reajuste_origem_por_fonte(fonte_de_recursos.id).to_f
	end

	def pode_excluir?
		if self.dotacoes_destino.any?
			self.dotacoes_destino.each do |dotacao_destino|
				if (dotacao_destino.orcamento_da_despesa.try(:saldo).to_f - dotacao_destino.valor.to_f) <= 0
					return false
				end
			end
			return true
		else
			return true
		end
	end

	def fonte_de_recurso_maior_ou_menor
		destino_maior = false
		origem_maior = false
		if self.dotacoes_destino.present? && self.dotacoes_origem.present?
			dotacoes_destino = self.dotacoes_destino.group_by { |dotacao_destino| dotacao_destino.orcamento_da_despesa.fonte_de_recursos.codigo_completo }.sort rescue Array.new

			dotacoes_destino.each do |dotacao_destino|
				if dotacoes_destino.map { |fonte| fonte[0]}.include?(dotacao_destino[0])
					valor_por_fonte_destino = dotacao_destino[1].inject(0){ |total, fonte| total + fonte[:valor].to_f }
					valor_por_fonte_origem = self.dotacoes_origem.map { |dotacao_origem| dotacao_origem if dotacao_origem.orcamento_da_despesa.fonte_de_recursos.codigo_completo == dotacao_destino[0] }.sum(&:valor)

					if valor_por_fonte_destino > valor_por_fonte_origem
						destino_maior = true
					elsif valor_por_fonte_origem > valor_por_fonte_destino
						origem_maior = true
					end
				else
					destino_maior = true
				end
			end
		end

		if destino_maior && origem_maior
			return 'destino_maior_e_origem_maior'
		elsif destino_maior
			return 'destino_maior'
		elsif origem_maior
			return 'origem_maior'
		end
		return false
	end

	def valor_dotacao_destino_menor_que_zero
		if self.dotacoes_destino.present?
			dotacoes_destino = self.dotacoes_destino { |dotacao_destino| dotacao_destino }

			dotacoes_destino.each do |dotacao_destino|
				errors.add(:base, "O valor da dotação de Acréscimo não pode ser zero.") if dotacao_destino.valor.to_f <= 0 && !dotacao_destino.marked_for_destruction?
			end
		end
	end

	# ASSOCIAÇÕES
	def retorna_as_dotacoes_destino(contexto_atual)
		dotacoes_destino =
			if programa_de_governo.present?
				programa_de_governo.map(&:orcamentos_da_despesa)
			elsif programa_de_governo_da_solicitacao.present? && acao.present?
				acao.map(&:orcamentos_da_despesa)
			elsif possui_orcamentos_vinculados?
				retorna_orcamentos_vinculados
			elsif fonte_de_recursos.present?
				retorna_orcamentos_por_fonte(contexto_atual)
			else
				retorna_orcamentos_por_unidade(contexto_atual)
			end
	end

	def retorna_as_dotacoes_origem(contexto_atual, eh_gestao_de_orcamento)
		if eh_gestao_de_orcamento
			retorna_orcamentos_por_fonte(contexto_atual)
		else
			retorna_orcamento_da_unidade_orcamentaria(contexto_atual)
		end
	end

	def retorna_orcamentos_por_unidade(contexto_atual)
		orcamentos_atuais = contexto_atual.orcamentos_da_despesa
		if self.projeto_id.present?
			unidade_orcamentaria = self.try(:projeto).try(:pedido).unidade_orcamentaria
		else
			unidade_orcamentaria = self.try(:unidade_orcamentaria)
		end
		if unidade_orcamentaria.present?
			orcamentos_atuais.joins(elemento_de_despesa_por_subacao: {subacao: :unidade_orcamentaria}).where("loa_unidades_orcamentarias.id = ?", unidade_orcamentaria.id )
		elsif acao.present?
			acoes = acao.ids
			orcamentos_atuais.joins(elemento_de_despesa_por_subacao: {subacao: :acao}).where("loa_acoes.id in (?)", acoes)
		else
			orcamentos_atuais
		end
	end

	def retorna_orcamentos_por_fonte(contexto_atual)
		orcamentos_atuais = contexto_atual.orcamentos_da_despesa
			.includes(:fonte_de_recursos, elemento_de_despesa_por_subacao: [:elemento_de_despesa, subacao: :acao])

		fontes_ids =
			if unidade_orcamentaria.present?
				unidade_orcamentaria.fontes_de_recursos.ids.uniq
			elsif fonte_de_recursos.present?
				self.fonte_de_recursos_id
			else
				orcamento.fontes_de_recursos
			end

		fontes_escolhidas_ids =
			if programa_de_governo.present?
				programa_de_governo.each do |programa_de_governo|
					programa_de_governo.orcamentos_da_despesa.pluck(:fonte_de_recursos_id).uniq.select { |id| fontes_ids.include?(id) }
				end
			elsif programa_de_governo_da_solicitacao.present? && acao.present?
				acao.each do |acao|
					acao.orcamentos_da_despesa.pluck(:fonte_de_recursos_id).uniq.select { |id| fontes_ids.include?(id) }
				end
			elsif possui_orcamentos_vinculados?
				retorna_orcamentos_vinculados.pluck(:fonte_de_recursos_id).uniq.select { |id| fontes_ids.include?(id) }
			else
				fontes_ids
			end
		if fontes_escolhidas_ids.present?
			orcamentos_atuais.where(fonte_de_recursos_id: fontes_escolhidas_ids)
		end

		return orcamentos_atuais
	end

	def retorna_orcamento_da_unidade_orcamentaria(contexto_atual)
		contexto_atual.orcamentos_da_despesa.joins(elemento_de_despesa_por_subacao: [:subacao]).where(
			loa_subacoes: {
				unidade_orcamentaria_id: self.unidade_orcamentaria_id || contexto_atual.unidades_orcamentarias.ids
			}
		)
	end

	def atribui_codigo_disponivel
		if self.data_da_solicitacao.present?
			gerar_codigo(send(:data_da_solicitacao), :numero_da_alteracao_orcamentaria, :data_da_solicitacao, :orcamento_id, self.orcamento_id)
		elsif self.decreto&.data_da_legislacao.present?
			update_column(:data_da_legislacao, self.decreto.data_da_legislacao)
			gerar_codigo(send(:data_da_legislacao), :numero_da_alteracao_orcamentaria, :data_da_legislacao, :orcamento_id, self.orcamento_id)
		end
		update_column(:numero_da_alteracao_orcamentaria, self.numero_da_alteracao_orcamentaria)
	end

	# Crédito especial sem nova ação e sem novo programa
	def retorna_orcamentos_vinculados
		orcamentos_da_despesa_ids = []

		subacoes_da_solicitacao.each do |subacao|
			subacao.elementos_por_subacao_da_solicitacao.each do |elemento|
				elemento_de_despesa_por_subacao = Loa::ElementoDeDespesaPorSubacao.where(subacao_id: subacao.subacao_id, elemento_de_despesa_id: elemento.elemento_de_despesa_id).first

				elemento.fontes_por_elemento_da_subacao_da_solicitacao.each do |fonte|
					orcamentos_da_despesa_ids << Loa::OrcamentoDaDespesa.where(elemento_de_despesa_por_subacao_id: elemento_de_despesa_por_subacao.id, fonte_de_recursos_id: fonte.fonte_de_recursos_id).ids
				end
			end
		end
		return Loa::OrcamentoDaDespesa.where(id:orcamentos_da_despesa_ids.flatten).includes(:fonte_de_recursos, elemento_de_despesa_por_subacao: [:elemento_de_despesa, subacao: :acao])
	end

	#DADOS
	def fonte_de_recurso_da_alteracao
		if self.dotacoes_destino.any?
			self.dotacoes_destino.first.try(:orcamento_da_despesa).try(:fonte_de_recursos).try(:codigo_e_descricao)
		elsif self.dotacoes_origem.any?
			self.dotacoes_origem.first.try(:orcamento_da_despesa).try(:fonte_de_recursos).try(:codigo_e_descricao)
		end
	end

	# VALORES
	def valor_para_ajustar_no_decreto
		if self.anulacao_de_dotacao?
			(soma_dotacoes_origem - soma_dotacoes_destino).abs
		else
			0
		end
	end

	def valor_para_ajustar_no_decreto_real
		if self.anulacao_de_dotacao?
			(soma_dotacoes_origem - soma_dotacoes_destino)
		else
			0
		end
	end

	def soma_dotacoes_origem
		dotacoes_origem.inject(0) { |total, dotacao_origem| (total + dotacao_origem.valor.to_f) if dotacao_origem.present?}
	end

	def soma_dotacoes_destino
		dotacoes_destino.inject(0) { |total, dotacao_destino| (total + dotacao_destino.valor.to_f) if dotacao_destino.present?}
	end



	# AÇÕES
	def lancar_movimento_orcamentario
		self.dotacoes_origem.each do |dotacao_origem|

			if Contabilidade::LancamentoDoOrcamentoDaDespesa.where(modulo: dotacao_origem).any?
				Contabilidade::LancamentoDoOrcamentoDaDespesa.where(modulo: dotacao_origem).try(:destroy_all)
			end


			if dotacao_origem.lancamento_do_orcamento_da_despesa.present? && dotacao_origem.valor > 0 && dotacao_origem.lancamento_do_orcamento_da_despesa.try(:valor) != dotacao_origem.valor
				dotacao_origem.send(:apagar_movimento_orcamentario)
			end
			

			if dotacao_origem.present? && dotacao_origem.valor != nil
				if dotacao_origem.lancamento_do_orcamento_da_despesa.present?
					dotacao_origem.send(:apagar_movimento_orcamentario)
				end

				movimentacao = Contabilidade::LancamentoDoOrcamentoDaDespesa.where(modulo: dotacao_origem).first_or_create(
					orcamento_da_despesa: dotacao_origem.orcamento_da_despesa,
					data_do_lancamento: self.decreto.data_da_legislacao,
					valor: dotacao_origem.valor,
					modulo: dotacao_origem
				)
				
				movimentacao.data_do_lancamento = self.decreto.data_da_legislacao if movimentacao.data_do_lancamento != self.decreto.data_da_legislacao
				movimentacao.valor = dotacao_origem.valor if movimentacao.valor != dotacao_origem.valor
				movimentacao.save
			end
		end

		self.dotacoes_destino.each do |dotacao_destino|

			if Contabilidade::LancamentoDoOrcamentoDaDespesa.find_by(modulo: dotacao_destino).present?
				Contabilidade::LancamentoDoOrcamentoDaDespesa.find_by(modulo: dotacao_destino).try(:destroy)
			end

			if dotacao_destino.lancamento_do_orcamento_da_despesa.present? && dotacao_destino.valor > 0 && dotacao_destino.lancamento_do_orcamento_da_despesa.try(:valor) != dotacao_destino.valor
				dotacao_destino.send(:apagar_movimento_orcamentario)
			end

			if dotacao_destino.present? && dotacao_destino.valor != nil
				movimentacao = Contabilidade::LancamentoDoOrcamentoDaDespesa.new(
					orcamento_da_despesa: dotacao_destino.orcamento_da_despesa,
					data_do_lancamento: self.decreto.data_da_legislacao,
					valor: dotacao_destino.valor,
					modulo: dotacao_destino
				)
				movimentacao.save
			end
		end
	end

	def apagar_movimento_orcamentario
		self.dotacoes_origem.each do |dotacao_origem|
			Contabilidade::LancamentoDoOrcamentoDaDespesa.find_by(modulo: dotacao_origem).try(:destroy)
		end

		self.dotacoes_destino.each do |dotacao_destino|
				Contabilidade::LancamentoDoOrcamentoDaDespesa.find_by(modulo: dotacao_destino).try(:destroy)
		end
	end

	# Crédito especial/extraordinário
	def atualiza_valor_das_fontes
		dotacoes_destino.each do |dotacao_destino|
			valor_do_orcamento = dotacao_destino.orcamento_da_despesa.valor_fixado
			valor_atualizado = valor_do_orcamento + dotacao_destino.valor
			dotacao_destino.orcamento_da_despesa.update_column(:valor, valor_atualizado)
		end
	end

	def adiciona_dotacoes_do_projeto_na_dotacao_destino
		self.projeto.orcamentos_da_despesa_por_projetos.each do |orcamento_da_despesa_por_projeto|
			if !orcamento_da_despesa_por_projeto.tem_saldo?

				dotacao_destino = Contabilidade::DotacaoDestino.new(
					orcamento_da_despesa: orcamento_da_despesa_por_projeto.orcamento_da_despesa,
					valor: orcamento_da_despesa_por_projeto.valor_de_diferenca_do_saldo,
					solicitacao_de_alteracao_orcamentaria: self
				)
				dotacao_destino.save
			end
		end
	end

	def adiciona_dotacao_do_empenho_na_dotacao_destino
		valor_a_suplementar = 0.0
		if self.empenho.present?
			orcamento_da_despesa = self.empenho.orcamento_da_despesa
			valor_a_suplementar = self.empenho.valor_do_defict_do_orcamento
		elsif self.orcamento_da_despesa_id
			orcamento_da_despesa = Loa::OrcamentoDaDespesa.find(self.orcamento_da_despesa_id)
		end

		dotacao_destino = Contabilidade::DotacaoDestino.new(
			orcamento_da_despesa: orcamento_da_despesa,
			valor: valor_a_suplementar.abs,
			solicitacao_de_alteracao_orcamentaria: self
		)
		dotacao_destino.save
	end

	def tipo_de_credito_to_sim
		if credito_suplementar?
			return "S"
		elsif credito_especial?
			return "E"
		elsif credito_extraordinario?
			return "X"
		end
	end

	def tipo_alteracao_orcamentaria_to_sim
		if self.decreto.remanejamento?
			return "R"
		elsif self.decreto.transposicao?
			return "T"
		elsif self.decreto.transferencias?
			return "F"
		end
	end

	def origem_do_recurso_to_sim
			if anulacao_de_dotacao?
				return "A"
			elsif execesso_de_arrecadacao?
				return "E"
			elsif superavit_financeiro?
				return "S"
			elsif revigoramento_de_credito?
				return "R"
			elsif operacao_de_credito?
				return "O"
			end
	end

	def valor_a_suplementar
		if dotacoes_destino.any?
			soma_dotacoes_destino
		elsif dotacoes_origem.any?
			soma_dotacoes_origem
		else
			0
		end
	end

	def soma_das_dotacoes_antigas
		dotacoes = 0.0
		if dotacoes_destino.any?
			dotacoes += dotacoes_destino.inject(0) { |total, dotacao_destino| (total + dotacao_destino.valor_was.to_f) if dotacao_destino.present?}
		elsif dotacoes_origem.any?
			dotacoes -= dotacoes_origem.inject(0) { |total, dotacao_origem| (total + dotacao_origem.valor_was.to_f) if dotacao_origem.present?}
		end
		return dotacoes
	end

	def remover_dotacoes_de_origem
		self.dotacoes_origem.each do |dotacao|
			dotacao.destroy
		end
	end

	def dotacoes_origem_enviada_ao_sim?
		dotacoes_origem.any? ? dotacoes_origem.where("arquivo_id IS null").empty? : false
	end

	def dotacoes_destino_enviada_ao_sim?
		dotacoes_destino.any? ? dotacoes_destino.where.not("arquivo_id IS null").empty? : false
	end

	def existem_dotacoes_destino_disponivel?
		if self.programa_de_governo.present?
			return self.programa_de_governo.any? { |programa| programa.orcamentos_da_despesa.any? }
		else
			return true
		end
	end

	def data_do_empenho_deve_estar_dentro_da_data_do_decreto
		if self.empenho.try(:data_de_solicitacao).try(:month) == self.decreto.try(:data_da_legislacao).try(:month) && self.empenho.try(:data_de_solicitacao).try(:year) == self.decreto.try(:data_da_legislacao).try(:year)
			if self.empenho.data_de_solicitacao > self.decreto.data_da_legislacao
				errors.add(:decreto_id, "Não pode ser inferior a data do empenho #{self.empenho.data_de_solicitacao}")
			end
		else
			errors.add(:decreto_id, "Mês do decreto deve ser igual ao mes do empenho #{self.empenho.try(:data_de_solicitacao)}")
		end
	end

	def data_do_projeto_deve_estar_dentro_da_data_do_decreto
		if self.projeto.try(:data_do_projeto).try(:month) == self.decreto.try(:data_da_legislacao).try(:month) && self.projeto.try(:data_do_projeto).try(:year) == self.decreto.try(:data_da_legislacao).try(:year)
			if self.projeto.data_do_projeto > self.decreto.data_da_legislacao
				errors.add(:decreto_id, "Não pode ser inferior a data do projeto #{self.projeto.data_do_projeto}")
			end
		else
			errors.add(:decreto_id, "Mês do decreto deve ser igual ao mes do projeto #{self.projeto.try(:data_do_projeto)}")
		end
	end

	def precisa_ser_de_credtio_especial
		unless self.credito_especial?
			dotacoes = []
			dotacoes_origem.joins(:orcamento_da_despesa).where('loa_orcamentos_da_despesa.valor = 0 AND de_credito_adicional IS FALSE').each{|dota| dotacoes << dota}
			dotacoes_destino.joins(:orcamento_da_despesa).where('loa_orcamentos_da_despesa.valor = 0 AND de_credito_adicional IS FALSE').each{|dota| dotacoes << dota}
			alerta = "As Dotações(#{dotacoes.map{|dota| dota.orcamento_da_despesa.classificacao_detalhada}.join(",")}) devem ser do tipo crédito especial, para continuar será necessário removê-las" if dotacoes.present?
		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?
	end

	def existe_lote_do_sim?(data_do_empenho = nil)
		if self.empenho.present?
			ultima_data = self.empenho.data_de_solicitacao
		else
			ultima_data = data_da_solicitacao || self.try(:decreto).try(:data_da_legislacao)
		end

		if ultima_data.present?
			lote_sim = Tcm::Lote.find_by(
				orcamento_id: orcamento_id,
				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 inconsistencia_no_sim?
		existe_lote_do_sim? && confirmado? == false
	end

	def tipo_de_movimentacao
		return '"1"'
	end

	def mes_bloqueado?
		if self.decreto.present?
			Contabilidade::BloqueioMensalDoPcasp.find_by(mes_referencia: self.decreto&.data_da_legislacao&.month, orcamento_id: self.decreto&.orcamento_id, bloqueado: true).present?
		else
			Contabilidade::BloqueioMensalDoPcasp.find_by(mes_referencia: self.data_da_solicitacao&.month, orcamento_id: self.orcamento_id, bloqueado: true).present?
		end
	end

	def pode_duplicar?
		(self.confirmado? || self.indeferido?) && self.decreto.aberto? && !self.mes_bloqueado?
	end

	def permite_adicionar_dotacoes
		self.execesso_de_arrecadacao? || self.superavit_financeiro?|| self.revigoramento_de_credito? || self.operacao_de_credito? || self.revigoramento_de_credito_especial? || self.revigoramento_de_credito_extraordinario? || self.reserva_de_contigencia?
	end	

	def somatorio_dotacoes_origem_por_fonte fonte_id
		return self.dotacoes_origem.joins(:orcamento_da_despesa).where("loa_orcamentos_da_despesa.fonte_de_recursos_id = ?", fonte_id).sum(&:valor)
	end

	def somatorio_dotacoes_destino_por_fonte fonte_id
		return self.dotacoes_destino.joins(:orcamento_da_despesa).where("loa_orcamentos_da_despesa.fonte_de_recursos_id = ?", fonte_id).sum(&:valor)
	end

	# def to_sim_credito_adicional(data_referencia, args)
	# 	begin
	# 		exercicio_do_orcamento = orcamento.exercicio.to_s

	# 		texto = ""
	# 		texto << "701".sim_preenche(3) + "," #01
	# 		texto << Configuracao.first.codigo_do_municipio_no_tcm.sim_preenche(3) + "," #02
	# 		texto << exercicio_do_orcamento.sim_limite_sem_aspas(6, "00") + "," #03
	# 		texto << decreto.try(:data_da_legislacao).sim_data + "," #04
	# 		texto << args[:sequencia].to_s + "," #05
	# 		texto << args[:orgao].sim_preenche(2) + "," #06
	# 		texto << args[:unidade_orcamentaria].to_s.sim_preenche(2) + "," #07
	# 		texto << args[:funcao].sim_limite(2)  + "," #08
	# 		texto << args[:subfuncao].sim_limite(3) + "," #09
	# 		texto << args[:programa_de_governo].sim_limite(4) + "," #10
	# 		texto << args[:natureza_da_acao].sim_limite(1) + "," #11
	# 		texto << args[:acao].sim_limite(3) + "," #12
	# 		if orcamento.trabalha_com_subacao?
	# 			texto << (args[:subacao].present? ? args[:subacao].sim_preenche(4) : '"0000"') + "," #13
	# 		else
	# 			texto << '"0000"' + "," #13
	# 		end
	# 		texto << args[:elemento_de_despesa].sim_preenche(8) + "," #14
	# 		texto << args[:fonte_de_recursos].first(1).sim_limite(1) + "," #15
	# 		texto << args[:fonte_de_recursos].last(9).sim_limite(9) + "," #16
	# 		texto << data_referencia.to_s + "," #17
	# 		texto << decreto.numero_da_lei.sim_limite(10) + "," #18
	# 		texto << decreto.numero.sim_limite(10) + "," #19
	# 		texto << args[:tipo_de_credito_to_sim].sim_limite(1) + "," #20
	# 		texto << args[:origem_do_recurso_to_sim].sim_limite(1) + "," #21
	# 		texto << args[:total_superavit_financeiro].round(2).to_d.to_s.sim_valor + "," #22
	# 		texto << args[:total_execesso_de_arrecadacao].round(2).to_d.to_s.sim_valor + "," #23
	# 		texto << args[:total_operacao_de_credito].round(2).to_d.to_s.sim_valor + "," #24
	# 		texto << args[:total_anulacao_de_dotacao].round(2).to_d.to_s.sim_valor #25

	# 		return texto
	# 	rescue => e
	# 		if e.class.to_s == "NoMethodError"
	# 			atributo_falho = e.message.split(" ")[2]
	# 			coluna = CSV.parse(texto, :headers => false).last.count
	# 			raise e.mensagem_traduzida(self, "", atributo_falho, coluna)
	# 		else
	# 			raise e
	# 		end
	# 	end
	# end

	def to_sim(data_referencia, dotacao_origem, dotacao_destino)
		# Variáveis necessárias para gerar o SIM
		exercicio_do_orcamento = orcamento.exercicio.to_s
		unidade_orcamentaria = dotacao_destino.orcamento_da_despesa.elemento_de_despesa_por_subacao.subacao.unidade_orcamentaria
		orgao = unidade_orcamentaria.orgao
		fonte = dotacao_destino.orcamento_da_despesa.fonte_de_recursos
		subacao = dotacao_destino.orcamento_da_despesa.elemento_de_despesa_por_subacao.subacao

		begin
			texto = ""
			texto << "705".sim_preenche(3) + "," #1
			texto << Configuracao.first.codigo_do_municipio_no_tcm.sim_preenche(3) + "," #2
			texto << exercicio_do_orcamento + '00' + "," #3
			texto << decreto.data_da_legislacao.sim_data + "," #4
			texto << numero_da_alteracao_orcamentaria.to_s.last(4) + "," #05
			texto << tipo_de_movimentacao + "," #6
			texto << unidade_orcamentaria.orgao.codigo.to_s.codigo_uo_to_sim + "," #7
			texto << unidade_orcamentaria.codigo.to_s.sim_preenche(2) + "," #8
			texto << subacao.funcao.codigo.sim_limite(2) + "," #9
			texto << subacao.subfuncao.codigo.sim_limite(3) + "," #10
			texto << dotacao_destino.orcamento_da_despesa.acao.programa_de_governo.codigo.sim_limite(4) + "," #11
			texto << dotacao_destino.orcamento_da_despesa.acao.natureza_da_acao.codigo.sim_limite(1) + "," #12
			texto << dotacao_destino.orcamento_da_despesa.acao.codigo.last(3).sim_limite(3) + "," #13
			texto << dotacao_destino.orcamento_da_despesa.subacao.codigo.to_s.sim_preenche(4) + "," #14
			texto << dotacao_destino.orcamento_da_despesa.elemento_de_despesa.codigo.sim_preenche(8) + "," #15
			texto << dotacao_origem.orcamento_da_despesa.fonte_de_recursos.codigo_completo.sim_preenche(1) + "," #16
			texto << dotacao_origem.orcamento_da_despesa.fonte_de_recursos.codigo_completo.last(9).sim_preenche(9) + "," #17
			texto << dotacao_destino.orcamento_da_despesa.fonte_de_recursos.codigo_completo.sim_preenche(1) + "," #18
			texto << dotacao_destino.orcamento_da_despesa.fonte_de_recursos.codigo_completo.last(9).sim_preenche(9) + "," #19
			texto << dotacao_destino.valor.to_f.to_s.sim_valor + "," #20
			texto << data_referencia.to_s  #21
		end
	end
end
