class Contabilidade::BalanceteDeVerificacao < ApplicationRecord
	attr_accessor :sem_fonte_de_recursos
	attr_accessor :tem_que_gerar_bens_do_balancete
	attr_default :tem_que_gerar_bens_do_balancete, false

	has_paper_trail

	belongs_to :orcamento, class_name: "Orcamento"
	has_many :movimentacoes_das_contas_do_balancete, class_name: "Contabilidade::MovimentacaoDaContaDoBalancete"
	has_many :bens_do_balancete, class_name: "Contabilidade::BemDoBalancete", dependent: :destroy
	has_many :contas_balancete_de_verificacao, class_name: "Contabilidade::ContaBalanceteDeVerificacao"
	has_many :dados_balancete_de_verificacao, class_name: "Contabilidade::DadoBalanceteDeVerificacao"

	accepts_nested_attributes_for :bens_do_balancete

	validates_presence_of :orcamento_id, :mes_de_referencia
	validates_uniqueness_of :mes_de_referencia, scope: :orcamento

	validate :verifica_se_mes_esta_bloqueado_antes_de_gerar_balancete

	after_create :gera_balancete
	after_create :gerar_dados_do_balancete
	after_destroy :apagar_movimentos

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

	def inicio_do_mes
		Date.new(self.orcamento.exercicio, Contabilidade::BalanceteDeVerificacao.mes_de_referencias[self.mes_de_referencia], 1)
	end

	def fim_do_mes
		Date.new(self.orcamento.exercicio, Contabilidade::BalanceteDeVerificacao.mes_de_referencias[self.mes_de_referencia], 1).end_of_month
	end

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

	def contas_por_orcamento
		orcamento.contas
	end

	def mes_bloqueado?
		if self.encerramento?
			true
		else
			orcamento.bloqueios_mensais_do_pcasp.find_by(mes_referencia: self.mes_de_referencia).bloqueado?
		end
	end

	def self.valor_total_creditos movimentacoes_ids
		Contabilidade::MovimentacaoDaContaDoBalancete.where(id: movimentacoes_ids).credito.joins(:movimentacao_do_plano_de_contas).where("COALESCE(contabilidade_movimentacoes_do_plano_de_contas.lancamento_manual, 0) != 999").where("COALESCE(contabilidade_movimentacoes_do_plano_de_contas.lancamento_manual, 0) != 1000").sum(:valor).to_f
	end

	def self.valor_total_creditos_por_mes movimentacoes_ids, data
		data_inicio = ("01/" << "#{data.month.to_s}/" << data.year.to_s).to_date
		data_fim = data
		Contabilidade::MovimentacaoDaContaDoBalancete.where(id: movimentacoes_ids).credito.joins(:movimentacao_do_plano_de_contas).where('data_de_lancamento >= ? and data_de_lancamento <= ?', data_inicio, data_fim).where("COALESCE(contabilidade_movimentacoes_do_plano_de_contas.lancamento_manual, 0) != 999").where("COALESCE(contabilidade_movimentacoes_do_plano_de_contas.lancamento_manual, 0) != 1000").sum(:valor).to_f
	end

	def self.valor_total_debitos movimentacoes_ids
		Contabilidade::MovimentacaoDaContaDoBalancete.where(id: movimentacoes_ids).debito.joins(:movimentacao_do_plano_de_contas).where("COALESCE(contabilidade_movimentacoes_do_plano_de_contas.lancamento_manual, 0) != 999").where("COALESCE(contabilidade_movimentacoes_do_plano_de_contas.lancamento_manual, 0) != 1000").sum(:valor).to_f
	end

	def self.valor_total_debitos_por_mes movimentacoes_ids, data
		data_inicio = ("01/" << "#{data.month.to_s}/" << data.year.to_s).to_date
		data_fim = data
		Contabilidade::MovimentacaoDaContaDoBalancete.where(id: movimentacoes_ids).debito.joins(:movimentacao_do_plano_de_contas).where('data_de_lancamento >= ? and data_de_lancamento <= ?', data_inicio, data_fim).where("COALESCE(contabilidade_movimentacoes_do_plano_de_contas.lancamento_manual, 0) != 999").where("COALESCE(contabilidade_movimentacoes_do_plano_de_contas.lancamento_manual, 0) != 1000").sum(:valor).to_f
	end

	def self.valor_total_creditos_agregado_por_periodo(conta, data_inicio, data_fim, unidade_orcamentaria = nil)
		attrs_busca = conta.classificacao_com_niveis_preenchidos
		outras_condicoes = []
		if unidade_orcamentaria.present?
			outras_condicoes << "contabilidade_movimentacoes_do_plano_de_contas.unidade_orcamentaria_id = #{unidade_orcamentaria.id}"
		end
		Contabilidade::MovimentacaoDaContaDoBalancete.joins(:conta).where(contabilidade_contas: attrs_busca).credito.joins(:movimentacao_do_plano_de_contas).where("#{outras_condicoes.join(" AND ")}").where('data_de_lancamento >= ? and data_de_lancamento <= ?', data_inicio, data_fim).sum(:valor).to_f
	end

	def self.valor_total_creditos_agregado_anterior_ao_mes conta, data_inicio
		data_inicio =  ("01/" << "#{data_inicio.month.to_s}/" << data_inicio.year.to_s).to_date
		attrs_busca = conta.classificacao_com_niveis_preenchidos
		Contabilidade::MovimentacaoDaContaDoBalancete.joins(:conta).where(contabilidade_contas: attrs_busca).credito.joins(:movimentacao_do_plano_de_contas).where('data_de_lancamento < ?', data_inicio).where("COALESCE(contabilidade_movimentacoes_do_plano_de_contas.lancamento_manual, 0) != 999").where("COALESCE(contabilidade_movimentacoes_do_plano_de_contas.lancamento_manual, 0) != 1000").sum(:valor).to_f
	end

	def self.valor_total_debitos_agregado_por_periodo(conta, data_inicio, data_fim, unidade_orcamentaria = nil)
		attrs_busca = conta.classificacao_com_niveis_preenchidos
		outras_condicoes = []
		if unidade_orcamentaria.present?
			outras_condicoes << "contabilidade_movimentacoes_do_plano_de_contas.unidade_orcamentaria_id = #{unidade_orcamentaria.id}"
		end
		Contabilidade::MovimentacaoDaContaDoBalancete.joins(:conta).where(contabilidade_contas: attrs_busca).debito.joins(:movimentacao_do_plano_de_contas).where("#{outras_condicoes.join(" AND ")}").where('data_de_lancamento >= ? and data_de_lancamento <= ?', data_inicio, data_fim).sum(:valor).to_f
	end

	def self.valor_total_debitos_agregado_anterior_ao_mes conta, data_inicio
		data_inicio =  ("01/" << "#{data_inicio.month.to_s}/" << data_inicio.year.to_s).to_date
		attrs_busca = conta.classificacao_com_niveis_preenchidos

		Contabilidade::MovimentacaoDaContaDoBalancete.joins(:conta).where(contabilidade_contas: attrs_busca).debito.joins(:movimentacao_do_plano_de_contas).where('data_de_lancamento < ?', data_inicio).where("COALESCE(contabilidade_movimentacoes_do_plano_de_contas.lancamento_manual, 0) != 999").where("COALESCE(contabilidade_movimentacoes_do_plano_de_contas.lancamento_manual, 0) != 1000").sum(:valor).to_f
	end

	def self.calcula_saldo_inicial_da_conta_baseado_no_mes(conta, movimentacoes_ate_a_data_inicial, movimentacoes_de_abertura = [])
		saldo_inicial = conta.saldo_inicial

		total_credito_abertura = movimentacoes_de_abertura.size > 0 ? movimentacoes_de_abertura.credito.sum(:valor) : 0
		total_debito_abertura = movimentacoes_de_abertura.size > 0 ? movimentacoes_de_abertura.debito.sum(:valor) : 0

		total_credito = movimentacoes_ate_a_data_inicial.size > 0 ? movimentacoes_ate_a_data_inicial.credito.sum(:valor) : 0
		total_debito = movimentacoes_ate_a_data_inicial.size > 0 ? movimentacoes_ate_a_data_inicial.debito.sum(:valor) : 0

		if conta.credor? || conta.mista?
			saldo_inicial - total_debito + total_debito_abertura + total_credito + total_credito_abertura
		else
			saldo_inicial + total_debito + total_debito_abertura - total_credito - total_credito_abertura
		end
	end

	def self.saldo_inicial_da_conta_baseado_no_mes(conta, data_inicio, unidade_orcamentaria = nil, poder_associado = nil, fonte_de_recursos_id = nil, ic_nr = nil, conta_bancaria_id = nil, codigo_fonte_de_recursos = nil)
		saldo_inicial = conta.saldo_inicial

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

		if ic_nr.present?
			if fonte_de_recursos_id.present?
				outras_condicoes << "contabilidade_movimentacoes_do_plano_de_contas.fonte_de_recursos_id = #{fonte_de_recursos_id}"
			elsif codigo_fonte_de_recursos.present?
				outras_condicoes << "contabilidade_movimentacoes_do_plano_de_contas.codigo_completo_fr = '#{codigo_fonte_de_recursos}'"
			else
				outras_condicoes << "contabilidade_movimentacoes_do_plano_de_contas.fonte_de_recursos_id is null"
			end
		else
			if fonte_de_recursos_id.present?
				outras_condicoes << "contabilidade_movimentacoes_do_plano_de_contas.fonte_de_recursos_id = #{fonte_de_recursos_id}"
			elsif codigo_fonte_de_recursos.present?
				outras_condicoes << "contabilidade_movimentacoes_do_plano_de_contas.codigo_completo_fr = '#{codigo_fonte_de_recursos}'"
			end
		end

		if conta_bancaria_id.present?
			outras_condicoes << "contabilidade_movimentacoes_do_plano_de_contas.conta_bancaria_id = #{conta_bancaria_id}"
		end

		if ic_nr.present?
			outras_condicoes << "ic_nr = '#{ic_nr}'"
		end

		movimentacoes_ate_a_data_inicial = []
		movimentacoes_de_abertura = []

		if data_inicio.month == 1
			movimentacoes_de_abertura = conta.movimentacoes_do_plano_de_contas.joins(unidade_orcamentaria: :tipo_de_unidade_administrativa)
				.where('extract(year from data_de_lancamento) = ?', data_inicio.year)
				.where("contabilidade_movimentacoes_do_plano_de_contas.lancamento_manual = 999")
				.where("#{outras_condicoes.join(" AND ")}")
		else
			movimentacoes_ate_a_data_inicial = conta.movimentacoes_do_plano_de_contas.joins(unidade_orcamentaria: :tipo_de_unidade_administrativa)
				.where('data_de_lancamento < ? AND extract(year from data_de_lancamento) = ?', data_inicio.beginning_of_month, data_inicio.year)
				.where("coalesce(contabilidade_movimentacoes_do_plano_de_contas.lancamento_manual, 0) != 999").sem_encerramento
				.where("#{outras_condicoes.join(" AND ")}")

			movimentacoes_de_abertura = conta.movimentacoes_do_plano_de_contas.joins(unidade_orcamentaria: :tipo_de_unidade_administrativa)
				.where('data_de_lancamento <= ? AND extract(year from data_de_lancamento) = ?', data_inicio.beginning_of_month, data_inicio.year)
				.where("contabilidade_movimentacoes_do_plano_de_contas.lancamento_manual = 999")
				.where("#{outras_condicoes.join(" AND ")}")
		end

		self.calcula_saldo_inicial_da_conta_baseado_no_mes(conta, movimentacoes_ate_a_data_inicial, movimentacoes_de_abertura)
	end

	def self.saldo_inicial_do_balancete_por_hash(conta, movimentacoes, data_inicio, unidade_gestora_id = nil, poder_associado = nil, fonte_de_recursos_id = nil, ic_nr = nil, conta_bancaria_id = nil, codigo_fonte_de_recursos = nil)
		saldo_inicial = conta[:saldo_inicial]

		movimentacoes = movimentacoes.select {|i| i[:codigo_da_conta] == conta[:codigo]}

		if unidade_gestora_id.present?
			movimentacoes = movimentacoes.select { |i| i[:unidade_gestora_id] == unidade_gestora_id }
		else
			movimentacoes = movimentacoes.select { |i| i[:unidade_gestora_id].nil? }
		end

		if poder_associado.present?
			movimentacoes = movimentacoes.select { |i| i[:poder_associado] = poder_associado }
		end

		if ic_nr.present?
			if fonte_de_recursos_id.present?
				movimentacoes = movimentacoes.select{ |i| i[:fonte_de_recursos_id] == fonte_de_recursos_id }
			elsif codigo_fonte_de_recursos.present?
				movimentacoes = movimentacoes.select{ |i| i[:codigo_completo_fr] == codigo_fonte_de_recursos }
			else
				movimentacoes = movimentacoes.select{ |i| i[:fonte_de_recursos_id].nil? }
			end
		else
			if fonte_de_recursos_id.present?
				movimentacoes = movimentacoes.select{ |i| i[:fonte_de_recursos_id] == fonte_de_recursos_id }
			elsif codigo_fonte_de_recursos.present?
				movimentacoes = movimentacoes.select{ |i| i[:codigo_completo_fr] == codigo_fonte_de_recursos }
			end
		end

		if conta_bancaria_id.present?
			movimentacoes = movimentacoes.select { |i| i[:conta_bancaria_id] == conta_bancaria_id }
		end

		if ic_nr.present?
			movimentacoes = movimentacoes.select { |i| i[:ic_nr] == ic_nr }
		end

		movimentacoes_ate_a_data_inicial = []
		movimentacoes_de_abertura = []

		if data_inicio.month == 1
			movimentacoes_de_abertura = movimentacoes.select { |i| i[:data_de_lancamento].year == data_inicio.year && i[:lancamento_manual] == 'abertura' }
		else
			movimentacoes_ate_a_data_inicial = movimentacoes.select { |i| 
				i[:data_de_lancamento] < data_inicio.beginning_of_month &&
				i[:data_de_lancamento].year == data_inicio.year &&
				i[:lancamento_manual] != 'abertura' &&
				i[:lancamento_manual] != 'encerramento'
			}

			movimentacoes_de_abertura = movimentacoes.select { |i| i[:data_de_lancamento] <= data_inicio.beginning_of_month && i[:data_de_lancamento].year == data_inicio.year &&	i[:lancamento_manual] == 'abertura'	}
		end

		self.calcula_saldo_inicial_do_balancete_por_hash(conta, movimentacoes_ate_a_data_inicial, movimentacoes_de_abertura)
	end

	def self.calcula_saldo_inicial_do_balancete_por_hash(conta, movimentacoes_ate_a_data_inicial, movimentacoes_de_abertura = [])
		saldo_inicial = conta[:saldo_inicial].to_d

		total_credito_abertura = movimentacoes_de_abertura.size > 0 ? movimentacoes_de_abertura.select { |i| i[:tipo_de_lancamento] == 'credito'}.map {|i| i[:valor]}.sum.to_d : 0
		total_debito_abertura = movimentacoes_de_abertura.size > 0 ? movimentacoes_de_abertura.select { |i| i[:tipo_de_lancamento] == 'debito'}.map {|i| i[:valor]}.sum.to_d : 0

		total_credito = movimentacoes_ate_a_data_inicial.size > 0 ? movimentacoes_ate_a_data_inicial.select { |i| i[:tipo_de_lancamento] == 'credito'}.map {|i| i[:valor]}.sum.to_d : 0
		total_debito = movimentacoes_ate_a_data_inicial.size > 0 ? movimentacoes_ate_a_data_inicial.select { |i| i[:tipo_de_lancamento] == 'debito'}.map {|i| i[:valor]}.sum.to_d : 0

		if conta[:natureza_do_saldo] == 'credor' || conta[:natureza_do_saldo] == 'mista'
			saldo_inicial - total_debito + total_debito_abertura + total_credito + total_credito_abertura
		else
			saldo_inicial + total_debito + total_debito_abertura - total_credito - total_credito_abertura
		end
	end

	def self.saldo_final_debitos conta
		(valor_total_creditos.to_f - valor_total_debitos.to_f).to_f + saldo_inicial_debitos.to_f
	end

	def self.saldo_final_creditos conta
		(valor_total_creditos.to_f - valor_total_debitos.to_f).to_f + saldo_inicial_creditos.to_f
	end

	def self.saldo_final conta
		(valor_total_creditos.to_f - valor_total_debitos.to_f).to_f + saldo_inicial.to_f
	end

	def self.saldo_inicial_debitos data_referencia, conta
		data_referencia_mes_anterior = data_referencia - 1.month
		conta.saldo_total_por_mes_debitos(data_referencia_mes_anterior).to_f
	end

	def self.saldo_inicial_creditos data_referencia, conta
		data_referencia_mes_anterior = data_referencia - 1.month
		conta.saldo_total_por_mes_creditos(data_referencia_mes_anterior).to_f
	end

	def self.saldo_inicial data_referencia, conta
		data_referencia_mes_anterior = data_referencia - 1.month
		conta.saldo_total_por_mes(data_referencia_mes_anterior).to_f
	end

	def gera_bens_do_balancete
		empenhos_de_aquisicao_de_imoveis_do_mes = Contabilidade::Empenho.confirmados.do_orcamento.where(
			"data_do_empenho >= ?
			AND data_do_empenho <= ?
			AND tipo_do_bem_do_empenho IS NOT NULL", data_referencia, data_referencia.end_of_month
		)
		empenhos_de_aquisicao_de_imoveis_do_mes.each do |empenho|
			Contabilidade::BemDoBalancete.create(
				balancete_de_verificacao_id: self.id,
				empenho_id: empenho.id,
				conta_id: empenho.tipo_do_bem_do_empenho,
				uso_do_bem: Contabilidade::BemDoBalancete.uso_do_bens[empenho.uso_do_bem_do_empenho.to_sym]
			)
		end
	end

	def lote_do_sim_finalizado?
		return false if self.encerramento?
		
		lote_sim = Tcm::Lote.find_by(
			orcamento_id: orcamento_id,
			tipo: [Tcm::Lote.tipos[:todos], Tcm::Lote.tipos[:contabilidade]],
			mes_de_referencia: self.mes_de_referencia,
			situacao: Tcm::Lote.situacoes[:finalizado]
		)
		return lote_sim.present?
	end

	def gera_balancete
		if self.encerramento?
			data_inicial = Date.new(self.orcamento.exercicio, 12)
			data_final = Date.new(self.orcamento.exercicio, 12).end_of_month
		else
			data_inicial = Date.new(self.orcamento.exercicio, Contabilidade::BalanceteDeVerificacao.mes_de_referencias[self.mes_de_referencia], 1)
			data_final = Date.new(self.orcamento.exercicio, Contabilidade::BalanceteDeVerificacao.mes_de_referencias[self.mes_de_referencia], 1).end_of_month
		end

		sql_command = <<-SQL
			insert into contabilidade_movimentacoes_das_contas_do_balancete
			(balancete_de_verificacao_id, conta_id, movimentacao_do_plano_de_contas_id, tipo_de_lancamento, created_at, updated_at)
			select :balancete_de_verificacao_id, conta_id, cmpc.id, cmpc.tipo_de_lancamento, now(), now() from contabilidade_movimentacoes_do_plano_de_contas as cmpc
			left join contabilidade_contas_por_eventos_contabeis ccpec on ccpec.id = cmpc.conta_por_evento_contabil_id
			where data_de_lancamento between :data_inicial and :data_final
		SQL

		ActiveRecord::Base.connection.execute(
			ApplicationRecord.sanitize_sql([sql_command, balancete_de_verificacao_id: self.id, data_inicial: data_inicial, data_final: data_final])
		)
	end

	def gerar_dados_do_balancete
		if self.encerramento?
			data_inicial = Date.new(self.orcamento.exercicio, 12)
			data_final = Date.new(self.orcamento.exercicio, 12).end_of_month
		else
			data_inicial = Date.new(self.orcamento.exercicio, Contabilidade::BalanceteDeVerificacao.mes_de_referencias[self.mes_de_referencia], 1)
			data_final = Date.new(self.orcamento.exercicio, Contabilidade::BalanceteDeVerificacao.mes_de_referencias[self.mes_de_referencia], 1).end_of_month
		end

		if self.encerramento?
			condicao_extra = " and coalesce(t1.lancamento_manual, 0) in (1000, 1001)"
		else
			condicao_extra = " and coalesce(t1.lancamento_manual, 0) != 1000"
		end

		sql_command = <<-SQL
				insert into contabilidade_dados_balancete_de_verificacao
				(balancete_de_verificacao_id, conta_id, codigo_da_conta, unidade_orcamentaria_id, tipo_de_lancamento, exercicio, competencia, valor, tipo_de_saldo, created_at, updated_at)
				select :balancete_de_verificacao_id, t2.conta_id, t3.codigo, t1.unidade_orcamentaria_id, t1.tipo_de_lancamento, 
				EXTRACT('year' from t1.data_de_lancamento) as exercicio, EXTRACT(MONTH from t1.data_de_lancamento) as competencia,
				sum(t1.valor) as valor, t1.tipo_de_lancamento as tipo_de_saldo, now(), now()
				from contabilidade_movimentacoes_do_plano_de_contas as t1
				left join contabilidade_contas_por_eventos_contabeis as t2 on t2.id = t1.conta_por_evento_contabil_id
				left join contabilidade_contas as t3 on t3.id = t2.conta_id
				where t1.data_de_lancamento between :data_inicial and :data_final
				and coalesce(t1.lancamento_manual, 0) != 999
				#{condicao_extra}
				group by t2.conta_id, t3.codigo, t1.unidade_orcamentaria_id, t1.tipo_de_lancamento,
				EXTRACT(YEAR from t1.data_de_lancamento), EXTRACT(MONTH from t1.data_de_lancamento)
		SQL

		ActiveRecord::Base.connection.execute(
			ApplicationRecord.sanitize_sql([sql_command, balancete_de_verificacao_id: self.id, data_inicial: data_inicial, data_final: data_final])
		)

		self.gerar_saldo_inicial_balancete
		self.gerar_saldo_final_balancete
	end

	def gerar_saldo_inicial_balancete
		if self.encerramento?
			data_inicial = Date.new(self.orcamento.exercicio, 12)
			data_final = Date.new(self.orcamento.exercicio, 12).end_of_month
		else
			data_inicial = Date.new(self.orcamento.exercicio, Contabilidade::BalanceteDeVerificacao.mes_de_referencias[self.mes_de_referencia], 1)
			data_final = Date.new(self.orcamento.exercicio, Contabilidade::BalanceteDeVerificacao.mes_de_referencias[self.mes_de_referencia], 1).end_of_month
		end

		if self.janeiro?
			sql_command = <<-SQL
					insert into contabilidade_dados_balancete_de_verificacao
					(balancete_de_verificacao_id, conta_id, codigo_da_conta, unidade_orcamentaria_id, tipo_de_lancamento, exercicio, competencia, valor, tipo_de_saldo, created_at, updated_at)
					select :balancete_de_verificacao_id, t2.conta_id, t3.codigo, t1.unidade_orcamentaria_id, 2, 
					EXTRACT('year' from t1.data_de_lancamento) as exercicio, EXTRACT(MONTH from t1.data_de_lancamento) as competencia,
					sum(t1.valor) as valor, t1.tipo_de_lancamento as tipo_de_saldo, now(), now()
					from contabilidade_movimentacoes_do_plano_de_contas as t1
					left join contabilidade_contas_por_eventos_contabeis as t2 on t2.id = t1.conta_por_evento_contabil_id
					left join contabilidade_contas as t3 on t3.id = t2.conta_id
					where t1.data_de_lancamento between :data_inicial and :data_final
					and coalesce(t1.lancamento_manual, 0) = 999
					group by t2.conta_id, t3.codigo, t1.unidade_orcamentaria_id, t1.tipo_de_lancamento,
					EXTRACT(YEAR from t1.data_de_lancamento), EXTRACT(MONTH from t1.data_de_lancamento)
			SQL

			ActiveRecord::Base.connection.execute(
				ApplicationRecord.sanitize_sql([sql_command, balancete_de_verificacao_id: self.id, data_inicial: data_inicial, data_final: data_final])
			)
		else
			sql_command = <<-SQL
				insert into contabilidade_dados_balancete_de_verificacao
				(balancete_de_verificacao_id, conta_id, codigo_da_conta, unidade_orcamentaria_id, tipo_de_lancamento, exercicio, 
				competencia, valor, tipo_de_saldo, created_at, updated_at)

				select :balancete_de_verificacao_id, t1.conta_id, t1.codigo_da_conta, t1.unidade_orcamentaria_id, 2, t1.exercicio,
				:compentencia, sum(t1.valor), t1.tipo_de_saldo, now(), now() from contabilidade_dados_balancete_de_verificacao as t1
				where t1.exercicio = :exercicio and t1.competencia = :competencia_consulta and t1.tipo_de_lancamento = 3
				group by t1.conta_id, t1.codigo_da_conta, t1.unidade_orcamentaria_id, t1.exercicio,
				t1.competencia, t1.tipo_de_saldo
			SQL

			if self.encerramento?
				competencia_a_pesquisar = 12
			else
				competencia_a_pesquisar = Contabilidade::BalanceteDeVerificacao.mes_de_referencias[self.mes_de_referencia] - 1
			end
			ActiveRecord::Base.connection.execute(
				ApplicationRecord.sanitize_sql([sql_command, balancete_de_verificacao_id: self.id, exercicio: self.orcamento.exercicio, compentencia: Contabilidade::BalanceteDeVerificacao.mes_de_referencias[self.mes_de_referencia], competencia_consulta: competencia_a_pesquisar])
			)
		end
	end

	def gerar_saldo_final_balancete
		if self.encerramento?
			data_inicial = Date.new(self.orcamento.exercicio, 12)
			data_final = Date.new(self.orcamento.exercicio, 12).end_of_month
		else
			data_inicial = Date.new(self.orcamento.exercicio, Contabilidade::BalanceteDeVerificacao.mes_de_referencias[self.mes_de_referencia], 1)
			data_final = Date.new(self.orcamento.exercicio, Contabilidade::BalanceteDeVerificacao.mes_de_referencias[self.mes_de_referencia], 1).end_of_month
		end

		sql_command = <<-SQL
			insert into contabilidade_dados_balancete_de_verificacao
			(balancete_de_verificacao_id, conta_id, codigo_da_conta, unidade_orcamentaria_id, tipo_de_lancamento, exercicio, 
			competencia, valor, tipo_de_saldo, created_at, updated_at)

			select :balancete_de_verificacao_id, t1.conta_id, t1.codigo_da_conta, t1.unidade_orcamentaria_id, 3, t1.exercicio,
			t1.competencia, sum(t1.valor), t1.tipo_de_saldo, now(), now() from contabilidade_dados_balancete_de_verificacao as t1
			where t1.balancete_de_verificacao_id = :balancete_de_verificacao_id
			group by t1.conta_id, t1.codigo_da_conta, t1.unidade_orcamentaria_id, t1.exercicio,
			t1.competencia, t1.tipo_de_saldo
		SQL

		ActiveRecord::Base.connection.execute(
			ApplicationRecord.sanitize_sql([sql_command, balancete_de_verificacao_id: self.id])
		)
	end

	def apagar_movimentos
		sql_command = <<-SQL
			delete from contabilidade_dados_balancete_de_verificacao where balancete_de_verificacao_id = :balancete_de_verificacao_id;
			delete from contabilidade_movimentacoes_das_contas_do_balancete where balancete_de_verificacao_id = :balancete_de_verificacao_id;
		SQL

		ActiveRecord::Base.connection.execute(
			ApplicationRecord.sanitize_sql([sql_command, balancete_de_verificacao_id: self.id])
		)
	end

	def verifica_se_mes_esta_bloqueado_antes_de_gerar_balancete
		unless self.mes_bloqueado?
			errors.add(:mes_de_referencia, "Para gerar o balancete de verificação é necessario primeiro bloquear o mês")
		end
	end

end
